skip to Main Content

Golang newbie here 🙂
I have a redis client wrapper over go-redis and I want to test that it works properly. I have tried using miniredis to mock the redis server I would be connecting to, but I keep getting an error.

When I have everything in the same function then this works – I am able to run go-redis against the miniredis service. However, when I try to use my client it fails.
I’ve tried looking in the docs of go-redis and miniredis but couldn’t find any answers. I’ve also tried having the miniredis server defined as a global variable but that didn’t help as well.

client impl:

package redis

import (
    "errors"
    "fmt"
    "github.com/go-redis/redis"
    "go.uber.org/zap"
    "os"
    "strconv"
    "time"
)

var redisClient *redis.Client
var redisCert string

var redisURL = "localhost:6379"
var redisPass = ""
var redisDB = 0

type Client struct {
    redisClient *redis.Client
}
func newRedisClient() *Client {
    if os.Getenv("REDIS_URL") != "" {
        redisURL = os.Getenv("REDIS_URL")
    }
    if os.Getenv("REDIS_PASS") != "" {
        redisPass = os.Getenv("REDIS_PASS")
    }
    if os.Getenv("REDIS_DB") != "" {
        redisDB, _ = strconv.Atoi(os.Getenv("REDIS_DB"))
    }

    client := redis.NewClient(&redis.Options{
        Addr:      redisURL,
        Password:  redisPass,
        DB:        redisDB,
    })
    redisClient = client
    _, err := redisClient.Ping().Result()
    if err != nil {
        fmt.Println("Failed to connect", zap.Error(err))
        return nil
    }
    fmt.Println("Redis client is ready")
    return &Client{redisClient: client}
}

func (r *Client) Get(key string) (string, error) {
    res, err := redisClient.Get(key).Result()
    fmt.Println(res, err)
    if err == redis.Nil {
        return "", errors.New("Key Not Found")
    } else if err != nil {
        return "", err
    } else {
        return res, nil
    }

}

Test impl:

package redis

import (
    "github.com/alicebob/miniredis/v2"
    "gopkg.in/go-playground/assert.v1"
    "os"
    "testing"
)

var mr *miniredis.Miniredis

func TestGet(t *testing.T) {
    mr, _ = miniredis.Run()
    mr.Set("test1", "some")
    os.Setenv("REDIS_URL", mr.Addr())
    c := newRedisClient()
    r, err := c.Get("test1")
    assert.Equal(t, r, "")
    assert.Equal(t, err, "")
    mr.Close()
}

What am I doing wrong?

2

Answers


  1. Sorry it took so long to come with a reply. I’ve run your code locally and I do not get an error.

    Normal file

    package redis
    
    import (
        "errors"
        "fmt"
        "os"
        "strconv"
    
        "github.com/go-redis/redis"
        "go.uber.org/zap"
    )
    
    var redisClient *redis.Client
    var redisCert string
    
    var redisURL = "localhost:6379"
    var redisPass = ""
    var redisDB = 0
    
    type Client struct {
        redisClient *redis.Client
    }
    
    func newRedisClient() *Client {
        if os.Getenv("REDIS_URL") != "" {
            redisURL = os.Getenv("REDIS_URL")
        }
        if os.Getenv("REDIS_PASS") != "" {
            redisPass = os.Getenv("REDIS_PASS")
        }
        if os.Getenv("REDIS_DB") != "" {
            redisDB, _ = strconv.Atoi(os.Getenv("REDIS_DB"))
        }
    
        client := redis.NewClient(&redis.Options{
            Addr:     redisURL,
            Password: redisPass,
            DB:       redisDB,
        })
        redisClient = client
        _, err := redisClient.Ping().Result()
        if err != nil {
            fmt.Println("Failed to connect", zap.Error(err))
            return nil
        }
        fmt.Println("Redis client is ready")
        return &Client{redisClient: client}
    }
    
    func (r *Client) Get(key string) (string, error) {
        res, err := redisClient.Get(key).Result()
        if err == redis.Nil {
            return "", errors.New("Key Not Found")
        } else if err != nil {
            return "", err
        } else {
            return res, nil
        }
    
    }
    

    Test file

    package redis
    
    import (
        "fmt"
        "os"
        "testing"
    
        "github.com/alicebob/miniredis/v2"
    )
    
    var mr *miniredis.Miniredis
    
    func TestGet(t *testing.T) {
        var err error
    
        mr, err = miniredis.Run()
        fmt.Printf("Run err: %vn", err)
        fmt.Printf("mr.Addr(): %vn", mr.Addr())
    
        err = mr.Set("test1", "some")
        fmt.Printf("Set err: %vn", err)
    
        err = os.Setenv("REDIS_URL", mr.Addr())
        fmt.Printf("Setenv err: %vn", err)
    
        c := newRedisClient()
        r, err := c.Get("test1")
    
        fmt.Printf("Get err: %vn", err)
        fmt.Printf("r: %vn", r)
    
        mr.Close()
    }
    

    Results

    go test
    Run err: <nil>
    mr.Addr(): 127.0.0.1:54966
    Set err: <nil>
    Setenv err: <nil>
    Redis client is ready
    Get err: <nil>
    r: some
    PASS
    ok      test/sof        0.536s
    
    Login or Signup to reply.
  2. Mock failed through miniredis, you can use SetError: https://github.com/alicebob/miniredis/issues/36#issuecomment-642009898

    func TestGet(t *testing.T) {
        mr, _ = miniredis.Run()
    
        // normal test
        // ...
    
        // error test
        mr.SetError("mock error")
        _, err = c.Get("test2")
        assert.EqualError(t, err, "mock error")
    
        mr.Close()
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search