Тестирование Голанга - насмешливый Redis

При тестировании наших приложений у нас часто возникает множество внешних зависимостей, и часто мы не запускаем наши тесты в среде, где у нас есть место для загрузки Redis, MySQL и т. Д.

Недавно я пытался решить проблему необходимости подключения Redis в одном из моих приложений, но я не хотел, чтобы сервер Redis работал, пока я проводил тесты, я чувствовал, что в этом нет необходимости.

Я наткнулся на элегантное решение этой проблемы: https://github.com/alicebob/miniredis

Эта библиотека запускает сервер, совместимый с Redis, в вашем приложении, который вы можете использовать без зависимостей при запуске тестов в любой среде. Это потрясающе!

Допустим, в вашем приложении вы используете redisClient, который доступен глобально в области вашего пакета:

В данном случае мы используем github.com/go-redis/redis в качестве предпочтительной библиотеки Redis.

package main

import (
    "log"
    "github.com/go-redis/redis"
)

var redisClient *redis.Client

func main() {
    redisClient = newRedisClient()
    
    doSomeRedisStuff()
}

func doSomeRedisStuff() bool {
    _, err = redisClient.Get("data").Result()
    
    return err != redis.Nil
}

func newRedisClient() *redis.Client {
    redisClient := redis.NewClient(&redis.Options{
        Addr:     "localhost:6579",
        Password: "", // no password set
        DB:       0,
    })
}

Как вы можете видеть в нашем main, мы создаем клиент Redis и подключаемся к локальному серверу.

В наших тестах нам не нужно РЕАЛЬНОЕ соединение.

Таким образом, мы можем смоделировать это, используя miniredis в нашей тестовой настройке:

package main

import (
    "testing"
    "time"
    "github.com/alicebob/miniredis"
    "github.com/stretchr/testify/assert"
)

var redisServer *miniredis.Miniredis

func testDoRedisStuffDataExists(t *testing.T) {
    setup()
    defer teardown()
    
    redisClient.Set("data", "something here", time.Minute)
  
    result := doSomeRedisStuff()
  
    assert.True(t, result, "We expect the 'data' to be in Redis")
}

func testDoRedisStuffDataDoesNotExist(t *testing.T) {
    setup()
    defer teardown()
  
    result := doSomeRedisStuff()
  
    assert.False(t, result, "We expect the 'data' to not be in Redis")
}

func mockRedis() *miniredis.Miniredis {
    s, err := miniredis.Run()

    if err != nil {
	panic(err)
    }

    return s
}

func setup() {
    redisServer = mockRedis()
    redisClient = redis.NewClient(&redis.Options{
	Addr: redisServer.Addr(),
    })
}

func teardown() {
    redisServer.Close()
}

Как видите, при создании макета «miniredis» мы получаем экземпляр сервера, который дает нам необходимую информацию, которую мы можем передать новым параметрам клиента при создании клиента Redis. Затем мы можем продолжать использовать клиент Redis так же, как и с настоящим соединением Redis.

Надеюсь, вы нашли это полезным! Пожалуйста, дайте мне знать, если вы обнаружите какие-либо проблемы с приведенными выше примерами; Я их не запускал. Они предназначены скорее как пример.