go单测-redismock使用

2039人浏览 / 0人评论

redismock提供redis请求的mock测试,兼容于github.com/go-redis/redis/v8

使用说明

1. 初始化

// RedisClient
redisClient, redisMock := redismock.NewClientMock() 

// RedisCluster
clusterClient, clusterMock := redismock.NewClusterMock() // redis集群
 RedisClientRedisCluster
不支持命令Subscribe / PSubscribeSubscribe / PSubscribe
Pipeline / TxPipeline
Watch
DBSize
 

对于基本数据结构读写,两者没有区别

2. mock使用

func SetData(client redis.UniversalClient, key string, value interface{}) (int, error) {
	ret, err := client.Set(context.TODO(), key, value, 0).Result()
	val, _ := strconv.Atoi(ret)
	return val, err
}
import (
	"testing"
	"github.com/go-redis/redismock/v8"
)

func TestSetData(t *testing.T) {
	redisClient, redisMock := redismock.NewClientMock()  // 初始化
	redisMock.ExpectSet("test", "value1", 0).SetVal("1") // 设置操作结果

	defer redisMock.ClearExpect()
	defer redisClient.Close()

	val, err := SetData(redisClient, "test", "value1")
	if val != 1 || err != nil {
		t.Errorf("SetData(), ret:%v, %v", val, err)
	}
}

常见错误

1. mock的操作和请求需要完全一致

type UserState int
func (v UserState) MarshalBinary() ([]byte, error) {
	return strconv.AppendInt([]byte{}, int64(v), 10), nil
}

const (
	UserStateOK     UserState = 1
	UserStateFailed UserState = 2
)

func TestSetData2(t *testing.T) {
	redisClient, redisMock := redismock.NewClientMock() // 初始化
	redisMock.ExpectSet("user_state", 1, 0).SetVal("1") // FAIL
	// redisMock.ExpectSet("user_state", UserStateOK, 0).SetVal("1") // SUCC
	defer redisMock.ClearExpect()
	defer redisClient.Close()

	val, err := SetData(redisClient, "user_state", UserStateOK)
	if val != 1 || err != nil {
		t.Errorf("SetData(), ret:%v, %v", val, err)
	}
}

自定义类型同样需要一致,否则会报错

SetData(), ret:0, args not `DeepEqual`, expectation: '1', but gave: '1'

2. mock的操作顺序和请求需要完全一致

func TestSetData3(t *testing.T) {
	redisClient, redisMock := redismock.NewClientMock()   // 初始化
	redisMock.ExpectSet("test2", "value2", 0).SetVal("1") // 设置操作结果
	redisMock.ExpectSet("test", "value1", 0).SetVal("1")  // 设置操作结果

	defer redisMock.ClearExpect()
	defer redisClient.Close()

	val, err := SetData(redisClient, "test", "value1")
	if val != 1 || err != nil {
		t.Errorf("SetData(), ret:%v, %v", val, err)
	}

	val, err = SetData(redisClient, "test2", "value2")
	if val != 1 || err != nil {
		t.Errorf("SetData(), ret:%v, %v", val, err)
	}
}
SetData(), ret:0, args not `DeepEqual`, expectation: 'test2', but gave: 'test'

3. mock的操作只支持请求一次

func TestSetData4(t *testing.T) {
	redisClient, redisMock := redismock.NewClientMock()  // 初始化
	redisMock.ExpectSet("test", "value1", 0).SetVal("1") // 设置操作结果

	defer redisMock.ClearExpect()
	defer redisClient.Close()

	val, err := SetData(redisClient, "test", "value1")
	if val != 1 || err != nil {
		t.Errorf("SetData(), ret:%v, %v", val, err)
	}

	val, err = SetData(redisClient, "test", "value1")
	if val != 1 || err != nil {
		t.Errorf("SetData(), ret:%v, %v", val, err)
	}
}
SetData(), ret:0, all expectations were already fulfilled, call to cmd '[set test value1]' was not expected

全部评论