diff --git a/commands_ft_test.go b/commands_ft_test.go new file mode 100644 index 0000000..8174bd2 --- /dev/null +++ b/commands_ft_test.go @@ -0,0 +1,253 @@ +package redismock + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/redis/go-redis/v9" +) + +var _ = Describe("FTCommands", func() { + var ( + clientMock baseMock + client mockCmdable + ) + + callCommandTest := func() { + It("ExpectFT_List", func() { + operationStringSliceCmd(clientMock, func() *ExpectedStringSlice { + return clientMock.ExpectFT_List() + }, func() *redis.StringSliceCmd { + return client.FT_List(ctx) + }) + }) + + It("ExpectFTAggregate", func() { + operationMapStringInterfaceCmd(clientMock, func() *ExpectedMapStringInterface { + return clientMock.ExpectFTAggregate("index", "query") + }, func() *redis.MapStringInterfaceCmd { + return client.FTAggregate(ctx, "index", "query") + }) + }) + + It("ExpectFTAggregateWithArgs", func() { + operationAggregateCmd(clientMock, func() *ExpectedAggregate { + return clientMock.ExpectFTAggregateWithArgs("index", "query", &redis.FTAggregateOptions{}) + }, func() *redis.AggregateCmd { + return client.FTAggregateWithArgs(ctx, "index", "query", &redis.FTAggregateOptions{}) + }) + }) + + It("ExpectFTAliasAdd", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTAliasAdd("index", "alias") + }, func() *redis.StatusCmd { + return client.FTAliasAdd(ctx, "index", "alias") + }) + }) + + It("ExpectFTAliasDel", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTAliasDel("alias") + }, func() *redis.StatusCmd { + return client.FTAliasDel(ctx, "alias") + }) + }) + + It("ExpectFTAliasUpdate", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTAliasUpdate("index", "alias") + }, func() *redis.StatusCmd { + return client.FTAliasUpdate(ctx, "index", "alias") + }) + }) + + It("ExpectFTAlter", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTAlter("index", false, []interface{}(nil)) + }, func() *redis.StatusCmd { + return client.FTAlter(ctx, "index", false, []interface{}(nil)) + }) + }) + + It("ExpectFTConfigGet", func() { + operationMapMapStringInterfaceCmd(clientMock, func() *ExpectedMapMapStringInterface { + return clientMock.ExpectFTConfigGet("option") + }, func() *redis.MapMapStringInterfaceCmd { + return client.FTConfigGet(ctx, "option") + }) + }) + + It("ExpectFTConfigSet", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTConfigSet("option", interface{}(nil)) + }, func() *redis.StatusCmd { + return client.FTConfigSet(ctx, "option", interface{}(nil)) + }) + }) + + It("ExpectFTCreate", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTCreate("index", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "test", FieldType: redis.SearchFieldTypeGeo}) + }, func() *redis.StatusCmd { + return client.FTCreate(ctx, "index", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "test", FieldType: redis.SearchFieldTypeGeo}) + }) + }) + + It("ExpectFTCursorDel", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTCursorDel("index", 0) + }, func() *redis.StatusCmd { + return client.FTCursorDel(ctx, "index", 0) + }) + }) + + It("ExpectFTCursorRead", func() { + operationMapStringInterfaceCmd(clientMock, func() *ExpectedMapStringInterface { + return clientMock.ExpectFTCursorRead("index", 0, 1) + }, func() *redis.MapStringInterfaceCmd { + return client.FTCursorRead(ctx, "index", 0, 1) + }) + }) + + It("ExpectFTDictAdd", func() { + operationIntCmd(clientMock, func() *ExpectedInt { + return clientMock.ExpectFTDictAdd("dict", "term") + }, func() *redis.IntCmd { + return client.FTDictAdd(ctx, "dict", "term") + }) + }) + + It("ExpectFTDictDel", func() { + operationIntCmd(clientMock, func() *ExpectedInt { + return clientMock.ExpectFTDictDel("dict", "term") + }, func() *redis.IntCmd { + return client.FTDictDel(ctx, "dict", "term") + }) + }) + + It("ExpectFTDictDump", func() { + operationStringSliceCmd(clientMock, func() *ExpectedStringSlice { + return clientMock.ExpectFTDictDump("dict") + }, func() *redis.StringSliceCmd { + return client.FTDictDump(ctx, "dict") + }) + }) + + It("ExpectFTDropIndex", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTDropIndex("index") + }, func() *redis.StatusCmd { + return client.FTDropIndex(ctx, "index") + }) + }) + + It("ExpectFTDropIndexWithArgs", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTDropIndexWithArgs("index", &redis.FTDropIndexOptions{}) + }, func() *redis.StatusCmd { + return client.FTDropIndexWithArgs(ctx, "index", &redis.FTDropIndexOptions{}) + }) + }) + + It("ExpectFTExplain", func() { + operationStringCmd(clientMock, func() *ExpectedString { + return clientMock.ExpectFTExplain("key", "query") + }, func() *redis.StringCmd { + return client.FTExplain(ctx, "key", "query") + }) + }) + + It("ExpectFTExplainWithArgs", func() { + operationStringCmd(clientMock, func() *ExpectedString { + return clientMock.ExpectFTExplainWithArgs("key", "query", &redis.FTExplainOptions{}) + }, func() *redis.StringCmd { + return client.FTExplainWithArgs(ctx, "key", "query", &redis.FTExplainOptions{}) + }) + }) + + It("ExpectFTInfo", func() { + operationFTInfoCmd(clientMock, func() *ExpectedFTInfo { + return clientMock.ExpectFTInfo("index") + }, func() *redis.FTInfoCmd { + return client.FTInfo(ctx, "index") + }) + }) + + It("ExpectFTSpellCheck", func() { + operationFTSpellCheckCmd(clientMock, func() *ExpectedFTSpellCheck { + return clientMock.ExpectFTSpellCheck("index", "query") + }, func() *redis.FTSpellCheckCmd { + return client.FTSpellCheck(ctx, "index", "query") + }) + }) + + It("ExpectFTSpellCheckWithArgs", func() { + operationFTSpellCheckCmd(clientMock, func() *ExpectedFTSpellCheck { + return clientMock.ExpectFTSpellCheckWithArgs("index", "query", &redis.FTSpellCheckOptions{}) + }, func() *redis.FTSpellCheckCmd { + return client.FTSpellCheckWithArgs(ctx, "index", "query", &redis.FTSpellCheckOptions{}) + }) + }) + + It("ExpectFTSearch", func() { + operationFTSearchCmd(clientMock, func() *ExpectedFTSearch { + return clientMock.ExpectFTSearch("index", "query") + }, func() *redis.FTSearchCmd { + return client.FTSearch(ctx, "index", "query") + }) + }) + + It("ExpectFTSearchWithArgs", func() { + operationFTSearchCmd(clientMock, func() *ExpectedFTSearch { + return clientMock.ExpectFTSearchWithArgs("index", "query", &redis.FTSearchOptions{}) + }, func() *redis.FTSearchCmd { + return client.FTSearchWithArgs(ctx, "index", "query", &redis.FTSearchOptions{}) + }) + }) + + It("ExpectFTSynDump", func() { + operationFTSynDumpCmd(clientMock, func() *ExpectedFTSynDump { + return clientMock.ExpectFTSynDump("index") + }, func() *redis.FTSynDumpCmd { + return client.FTSynDump(ctx, "index") + }) + }) + + It("ExpectFTSynUpdate", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTSynUpdate("index", interface{}(nil), []interface{}{}) + }, func() *redis.StatusCmd { + return client.FTSynUpdate(ctx, "index", interface{}(nil), []interface{}{}) + }) + }) + + It("ExpectFTSynUpdateWithArgs", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectFTSynUpdateWithArgs("index", interface{}(nil), &redis.FTSynUpdateOptions{}, []interface{}{}) + }, func() *redis.StatusCmd { + return client.FTSynUpdateWithArgs(ctx, "index", interface{}(nil), &redis.FTSynUpdateOptions{}, []interface{}{}) + }) + }) + + It("ExpectFTTagVals", func() { + operationStringSliceCmd(clientMock, func() *ExpectedStringSlice { + return clientMock.ExpectFTTagVals("index", "field") + }, func() *redis.StringSliceCmd { + return client.FTTagVals(ctx, "index", "field") + }) + }) + } + + Describe("client", func() { + BeforeEach(func() { + client, clientMock = NewClientMock() + }) + + AfterEach(func() { + Expect(client.(*redis.Client).Close()).NotTo(HaveOccurred()) + Expect(clientMock.ExpectationsWereMet()).NotTo(HaveOccurred()) + }) + + callCommandTest() + }) +}) diff --git a/commands_json_test.go b/commands_json_test.go new file mode 100644 index 0000000..ef73b27 --- /dev/null +++ b/commands_json_test.go @@ -0,0 +1,241 @@ +package redismock + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/redis/go-redis/v9" +) + +var _ = Describe("JSONCommands", func() { + var ( + clientMock baseMock + client mockCmdable + ) + + callCommandTest := func() { + It("ExpectJSONArrAppend", func() { + operationIntSliceCmd(clientMock, func() *ExpectedIntSlice { + return clientMock.ExpectJSONArrAppend("key", "path", "value") + }, func() *redis.IntSliceCmd { + return client.JSONArrAppend(ctx, "key", "path", "value") + }) + }) + + It("ExpectJSONArrIndex", func() { + operationIntSliceCmd(clientMock, func() *ExpectedIntSlice { + return clientMock.ExpectJSONArrIndex("key", "path", "value") + }, func() *redis.IntSliceCmd { + return client.JSONArrIndex(ctx, "key", "path", "value") + }) + }) + + It("ExpectJSONArrIndexWithArgs", func() { + operationIntSliceCmd(clientMock, func() *ExpectedIntSlice { + return clientMock.ExpectJSONArrIndexWithArgs("key", "path", &redis.JSONArrIndexArgs{}, "value") + }, func() *redis.IntSliceCmd { + return client.JSONArrIndexWithArgs(ctx, "key", "path", &redis.JSONArrIndexArgs{}, "value") + }) + }) + + It("ExpectJSONArrInsert", func() { + operationIntSliceCmd(clientMock, func() *ExpectedIntSlice { + return clientMock.ExpectJSONArrInsert("key", "path", 1, "value") + }, func() *redis.IntSliceCmd { + return client.JSONArrInsert(ctx, "key", "path", 1, "value") + }) + }) + + It("ExpectJSONArrLen", func() { + operationIntSliceCmd(clientMock, func() *ExpectedIntSlice { + return clientMock.ExpectJSONArrLen("key", "path") + }, func() *redis.IntSliceCmd { + return client.JSONArrLen(ctx, "key", "path") + }) + }) + + It("ExpectJSONArrPop", func() { + operationStringSliceCmd(clientMock, func() *ExpectedStringSlice { + return clientMock.ExpectJSONArrPop("key", "path", 1) + }, func() *redis.StringSliceCmd { + return client.JSONArrPop(ctx, "key", "path", 1) + }) + }) + + It("ExpectJSONArrTrim", func() { + operationIntSliceCmd(clientMock, func() *ExpectedIntSlice { + return clientMock.ExpectJSONArrTrim("key", "path") + }, func() *redis.IntSliceCmd { + return client.JSONArrTrim(ctx, "key", "path") + }) + }) + + It("ExpectJSONArrTrimWithArgs", func() { + operationIntSliceCmd(clientMock, func() *ExpectedIntSlice { + return clientMock.ExpectJSONArrTrimWithArgs("key", "path", &redis.JSONArrTrimArgs{}) + }, func() *redis.IntSliceCmd { + return client.JSONArrTrimWithArgs(ctx, "key", "path", &redis.JSONArrTrimArgs{}) + }) + }) + + It("ExpectJSONClear", func() { + operationIntCmd(clientMock, func() *ExpectedInt { + return clientMock.ExpectJSONClear("key", "path") + }, func() *redis.IntCmd { + return client.JSONClear(ctx, "key", "path") + }) + }) + + It("ExpectJSONDebugMemory", func() { + Skip("ExpectJSONDebugMemory just panics") + }) + + It("ExpectJSONDel", func() { + operationIntCmd(clientMock, func() *ExpectedInt { + return clientMock.ExpectJSONDel("key", "path") + }, func() *redis.IntCmd { + return client.JSONDel(ctx, "key", "path") + }) + }) + + It("ExpectJSONForget", func() { + operationIntCmd(clientMock, func() *ExpectedInt { + return clientMock.ExpectJSONForget("key", "path") + }, func() *redis.IntCmd { + return client.JSONForget(ctx, "key", "path") + }) + }) + + It("ExpectJSONGet", func() { + operationJSONCmd(clientMock, func() *ExpectedJSON { + return clientMock.ExpectJSONGet("key", "paths") + }, func() *redis.JSONCmd { + return client.JSONGet(ctx, "key", "paths") + }) + }) + + It("ExpectJSONGetWithArgs", func() { + operationJSONCmd(clientMock, func() *ExpectedJSON { + return clientMock.ExpectJSONGetWithArgs("key", &redis.JSONGetArgs{}, "paths") + }, func() *redis.JSONCmd { + return client.JSONGetWithArgs(ctx, "key", &redis.JSONGetArgs{}, "paths") + }) + }) + + It("ExpectJSONMerge", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectJSONMerge("key", "path", "value") + }, func() *redis.StatusCmd { + return client.JSONMerge(ctx, "key", "path", "value") + }) + }) + + It("ExpectJSONMSetArgs", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectJSONMSetArgs([]redis.JSONSetArgs{}) + }, func() *redis.StatusCmd { + return client.JSONMSetArgs(ctx, []redis.JSONSetArgs{}) + }) + }) + + It("ExpectJSONMSet", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectJSONMSet("params") + }, func() *redis.StatusCmd { + return client.JSONMSet(ctx, "params") + }) + }) + + It("ExpectJSONMGet", func() { + operationJSONSliceCmd(clientMock, func() *ExpectedJSONSlice { + return clientMock.ExpectJSONMGet("path", "keys") + }, func() *redis.JSONSliceCmd { + return client.JSONMGet(ctx, "path", "keys") + }) + }) + + It("ExpectJSONNumIncrBy", func() { + operationJSONCmd(clientMock, func() *ExpectedJSON { + return clientMock.ExpectJSONNumIncrBy("key", "path", 0.1) + }, func() *redis.JSONCmd { + return client.JSONNumIncrBy(ctx, "key", "path", 0.1) + }) + }) + + It("ExpectJSONObjKeys", func() { + operationSliceCmd(clientMock, func() *ExpectedSlice { + return clientMock.ExpectJSONObjKeys("key", "path") + }, func() *redis.SliceCmd { + return client.JSONObjKeys(ctx, "key", "path") + }) + }) + + It("ExpectJSONObjLen", func() { + operationIntPointerSliceCmd(clientMock, func() *ExpectedIntPointerSlice { + return clientMock.ExpectJSONObjLen("key", "path") + }, func() *redis.IntPointerSliceCmd { + return client.JSONObjLen(ctx, "key", "path") + }) + }) + + It("ExpectJSONSet", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectJSONSet("key", "path", "value") + }, func() *redis.StatusCmd { + return client.JSONSet(ctx, "key", "path", "value") + }) + }) + + It("ExpectJSONSetMode", func() { + operationStatusCmd(clientMock, func() *ExpectedStatus { + return clientMock.ExpectJSONSetMode("key", "path", "value", "NX") + }, func() *redis.StatusCmd { + return client.JSONSetMode(ctx, "key", "path", "value", "NX") + }) + }) + + It("ExpectJSONStrAppend", func() { + operationIntPointerSliceCmd(clientMock, func() *ExpectedIntPointerSlice { + return clientMock.ExpectJSONStrAppend("key", "path", "value") + }, func() *redis.IntPointerSliceCmd { + return client.JSONStrAppend(ctx, "key", "path", "value") + }) + }) + + It("ExpectJSONStrLen", func() { + operationIntPointerSliceCmd(clientMock, func() *ExpectedIntPointerSlice { + return clientMock.ExpectJSONStrLen("key", "path") + }, func() *redis.IntPointerSliceCmd { + return client.JSONStrLen(ctx, "key", "path") + }) + }) + + It("ExpectJSONToggle", func() { + operationIntPointerSliceCmd(clientMock, func() *ExpectedIntPointerSlice { + return clientMock.ExpectJSONToggle("key", "path") + }, func() *redis.IntPointerSliceCmd { + return client.JSONToggle(ctx, "key", "path") + }) + }) + + It("ExpectJSONType", func() { + operationJSONSliceCmd(clientMock, func() *ExpectedJSONSlice { + return clientMock.ExpectJSONType("key", "path") + }, func() *redis.JSONSliceCmd { + return client.JSONType(ctx, "key", "path") + }) + }) + } + + Describe("client", func() { + BeforeEach(func() { + client, clientMock = NewClientMock() + }) + + AfterEach(func() { + Expect(client.(*redis.Client).Close()).NotTo(HaveOccurred()) + Expect(clientMock.ExpectationsWereMet()).NotTo(HaveOccurred()) + }) + + callCommandTest() + }) +}) diff --git a/expect.go b/expect.go index c7c5b97..91872fe 100644 --- a/expect.go +++ b/expect.go @@ -394,6 +394,63 @@ type baseMock interface { ExpectTSMRevRangeWithArgs(fromTimestamp int, toTimestamp int, filterExpr []string, options *redis.TSMRevRangeOptions) *ExpectedMapStringSliceInterface ExpectTSMGet(filters []string) *ExpectedMapStringSliceInterface ExpectTSMGetWithArgs(filters []string, options *redis.TSMGetOptions) *ExpectedMapStringSliceInterface + + ExpectJSONArrAppend(key, path string, values ...interface{}) *ExpectedIntSlice + ExpectJSONArrIndex(key, path string, value ...interface{}) *ExpectedIntSlice + ExpectJSONArrIndexWithArgs(key, path string, options *redis.JSONArrIndexArgs, value ...interface{}) *ExpectedIntSlice + ExpectJSONArrInsert(key, path string, index int64, values ...interface{}) *ExpectedIntSlice + ExpectJSONArrLen(key, path string) *ExpectedIntSlice + ExpectJSONArrPop(key, path string, index int) *ExpectedStringSlice + ExpectJSONArrTrim(key, path string) *ExpectedIntSlice + ExpectJSONArrTrimWithArgs(key, path string, options *redis.JSONArrTrimArgs) *ExpectedIntSlice + ExpectJSONClear(key, path string) *ExpectedInt + // ExpectJSONDebugMemory(key, path string) *ExpectedInt // This just panics in the go-redis code + ExpectJSONDel(key, path string) *ExpectedInt + ExpectJSONForget(key, path string) *ExpectedInt + ExpectJSONGet(key string, paths ...string) *ExpectedJSON + ExpectJSONGetWithArgs(key string, options *redis.JSONGetArgs, paths ...string) *ExpectedJSON + ExpectJSONMerge(key, path string, value string) *ExpectedStatus + ExpectJSONMSetArgs(docs []redis.JSONSetArgs) *ExpectedStatus + ExpectJSONMSet(params ...interface{}) *ExpectedStatus + ExpectJSONMGet(path string, keys ...string) *ExpectedJSONSlice + ExpectJSONNumIncrBy(key, path string, value float64) *ExpectedJSON + ExpectJSONObjKeys(key, path string) *ExpectedSlice + ExpectJSONObjLen(key, path string) *ExpectedIntPointerSlice + ExpectJSONSet(key, path string, value interface{}) *ExpectedStatus + ExpectJSONSetMode(key, path string, value interface{}, mode string) *ExpectedStatus + ExpectJSONStrAppend(key, path, value string) *ExpectedIntPointerSlice + ExpectJSONStrLen(key, path string) *ExpectedIntPointerSlice + ExpectJSONToggle(key, path string) *ExpectedIntPointerSlice + ExpectJSONType(key, path string) *ExpectedJSONSlice + + ExpectFT_List() *ExpectedStringSlice + ExpectFTAggregate(index string, query string) *ExpectedMapStringInterface + ExpectFTAggregateWithArgs(index string, query string, options *redis.FTAggregateOptions) *ExpectedAggregate + ExpectFTAliasAdd(index string, alias string) *ExpectedStatus + ExpectFTAliasDel(alias string) *ExpectedStatus + ExpectFTAliasUpdate(index string, alias string) *ExpectedStatus + ExpectFTAlter(index string, skipInitialScan bool, definition []interface{}) *ExpectedStatus + ExpectFTConfigGet(option string) *ExpectedMapMapStringInterface + ExpectFTConfigSet(option string, value interface{}) *ExpectedStatus + ExpectFTCreate(index string, options *redis.FTCreateOptions, schema ...*redis.FieldSchema) *ExpectedStatus + ExpectFTCursorDel(index string, cursorId int) *ExpectedStatus + ExpectFTCursorRead(index string, cursorId int, count int) *ExpectedMapStringInterface + ExpectFTDictAdd(dict string, term ...interface{}) *ExpectedInt + ExpectFTDictDel(dict string, term ...interface{}) *ExpectedInt + ExpectFTDictDump(dict string) *ExpectedStringSlice + ExpectFTDropIndex(index string) *ExpectedStatus + ExpectFTDropIndexWithArgs(index string, options *redis.FTDropIndexOptions) *ExpectedStatus + ExpectFTExplain(index string, query string) *ExpectedString + ExpectFTExplainWithArgs(index string, query string, options *redis.FTExplainOptions) *ExpectedString + ExpectFTInfo(index string) *ExpectedFTInfo + ExpectFTSpellCheck(index string, query string) *ExpectedFTSpellCheck + ExpectFTSpellCheckWithArgs(index string, query string, options *redis.FTSpellCheckOptions) *ExpectedFTSpellCheck + ExpectFTSearch(index string, query string) *ExpectedFTSearch + ExpectFTSearchWithArgs(index string, query string, options *redis.FTSearchOptions) *ExpectedFTSearch + ExpectFTSynDump(index string) *ExpectedFTSynDump + ExpectFTSynUpdate(index string, synGroupId interface{}, terms []interface{}) *ExpectedStatus + ExpectFTSynUpdateWithArgs(index string, synGroupId interface{}, options *redis.FTSynUpdateOptions, terms []interface{}) *ExpectedStatus + ExpectFTTagVals(index string, field string) *ExpectedStringSlice } type pipelineMock interface { @@ -464,6 +521,7 @@ type expectedBase struct { setVal bool regexpMatch bool customMatch CustomMatch + rawVal interface{} rw sync.RWMutex } diff --git a/expect_ft.go b/expect_ft.go new file mode 100644 index 0000000..06c4e3a --- /dev/null +++ b/expect_ft.go @@ -0,0 +1,95 @@ +package redismock + +import ( + "github.com/redis/go-redis/v9" +) + +type ExpectedMapMapStringInterface struct { + expectedBase + + val map[string]interface{} +} + +func (cmd *ExpectedMapMapStringInterface) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedMapMapStringInterface) SetVal(val map[string]interface{}) { + cmd.setVal = true + cmd.val = val +} + +type ExpectedFTSearch struct { + expectedBase + + val redis.FTSearchResult +} + +func (cmd *ExpectedFTSearch) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedFTSearch) SetVal(val redis.FTSearchResult) { + cmd.setVal = true + cmd.val = val +} + +type ExpectedFTSpellCheck struct { + expectedBase + + val []redis.SpellCheckResult +} + +func (cmd *ExpectedFTSpellCheck) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedFTSpellCheck) SetVal(val []redis.SpellCheckResult) { + cmd.setVal = true + cmd.val = val +} + +type ExpectedAggregate struct { + expectedBase + + val *redis.FTAggregateResult +} + +func (cmd *ExpectedAggregate) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedAggregate) SetVal(val *redis.FTAggregateResult) { + cmd.setVal = true + cmd.val = val +} + +type ExpectedFTInfo struct { + expectedBase + + val redis.FTInfoResult +} + +func (cmd *ExpectedFTInfo) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedFTInfo) SetVal(val redis.FTInfoResult) { + cmd.setVal = true + cmd.val = val +} + +type ExpectedFTSynDump struct { + expectedBase + + val []redis.FTSynDumpResult +} + +func (cmd *ExpectedFTSynDump) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedFTSynDump) SetVal(val []redis.FTSynDumpResult) { + cmd.setVal = true + cmd.val = val +} diff --git a/expect_json.go b/expect_json.go new file mode 100644 index 0000000..fd18a55 --- /dev/null +++ b/expect_json.go @@ -0,0 +1,51 @@ +package redismock + +import ( + "github.com/redis/go-redis/v9" +) + +type ExpectedIntPointerSlice struct { + expectedBase + + val []*int64 +} + +func (cmd *ExpectedIntPointerSlice) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedIntPointerSlice) SetVal(val []*int64) { + cmd.setVal = true + cmd.val = val +} + +type ExpectedJSON struct { + expectedBase + + val string + expanded interface{} +} + +func (cmd *ExpectedJSON) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedJSON) SetVal(val string) { + cmd.setVal = true + cmd.val = val +} + +type ExpectedJSONSlice struct { + expectedBase + + val []interface{} +} + +func (cmd *ExpectedJSONSlice) inflow(c redis.Cmder) { + inflow(c, "val", cmd.val) +} + +func (cmd *ExpectedJSONSlice) SetVal(val []interface{}) { + cmd.setVal = true + cmd.val = val +} diff --git a/go.mod b/go.mod index bbc013e..fb5d9c1 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.25.0 - github.com/redis/go-redis/v9 v9.2.0 + github.com/redis/go-redis/v9 v9.7.0 ) require ( diff --git a/go.sum b/go.sum index 0151d92..3025949 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= -github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -38,10 +38,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/redis/go-redis/v9 v9.0.3 h1:+7mmR26M0IvyLxGZUHxu4GiBkJkVDid0Un+j4ScYu4k= -github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= -github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/mock_ft.go b/mock_ft.go new file mode 100644 index 0000000..c0a10ef --- /dev/null +++ b/mock_ft.go @@ -0,0 +1,199 @@ +package redismock + +import "github.com/redis/go-redis/v9" + +func (m *mock) ExpectFT_List() *ExpectedStringSlice { + e := &ExpectedStringSlice{} + e.cmd = m.factory.FT_List(m.ctx) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTAggregate(index string, query string) *ExpectedMapStringInterface { + e := &ExpectedMapStringInterface{} + e.cmd = m.factory.FTAggregate(m.ctx, index, query) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTAggregateWithArgs(index string, query string, options *redis.FTAggregateOptions) *ExpectedAggregate { + e := &ExpectedAggregate{} + e.cmd = m.factory.FTAggregateWithArgs(m.ctx, index, query, options) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTAliasAdd(index string, alias string) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTAliasAdd(m.ctx, index, alias) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTAliasDel(alias string) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTAliasDel(m.ctx, alias) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTAliasUpdate(index string, alias string) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTAliasUpdate(m.ctx, index, alias) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTAlter(index string, skipInitialScan bool, definition []interface{}) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTAlter(m.ctx, index, skipInitialScan, definition) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTConfigGet(option string) *ExpectedMapMapStringInterface { + e := &ExpectedMapMapStringInterface{} + e.cmd = m.factory.FTConfigGet(m.ctx, option) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTConfigSet(option string, value interface{}) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTConfigSet(m.ctx, option, value) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTCreate(index string, options *redis.FTCreateOptions, schema ...*redis.FieldSchema) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTCreate(m.ctx, index, options, schema...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTCursorDel(index string, cursorId int) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTCursorDel(m.ctx, index, cursorId) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTCursorRead(index string, cursorId int, count int) *ExpectedMapStringInterface { + e := &ExpectedMapStringInterface{} + e.cmd = m.factory.FTCursorRead(m.ctx, index, cursorId, count) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTDictAdd(dict string, term ...interface{}) *ExpectedInt { + e := &ExpectedInt{} + e.cmd = m.factory.FTDictAdd(m.ctx, dict, term...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTDictDel(dict string, term ...interface{}) *ExpectedInt { + e := &ExpectedInt{} + e.cmd = m.factory.FTDictDel(m.ctx, dict, term...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTDictDump(dict string) *ExpectedStringSlice { + e := &ExpectedStringSlice{} + e.cmd = m.factory.FTDictDump(m.ctx, dict) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTDropIndex(index string) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTDropIndex(m.ctx, index) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTDropIndexWithArgs(index string, options *redis.FTDropIndexOptions) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTDropIndexWithArgs(m.ctx, index, options) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTExplain(index string, query string) *ExpectedString { + e := &ExpectedString{} + e.cmd = m.factory.FTExplain(m.ctx, index, query) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTExplainWithArgs(index string, query string, options *redis.FTExplainOptions) *ExpectedString { + e := &ExpectedString{} + e.cmd = m.factory.FTExplainWithArgs(m.ctx, index, query, options) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTInfo(index string) *ExpectedFTInfo { + e := &ExpectedFTInfo{} + e.cmd = m.factory.FTInfo(m.ctx, index) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTSpellCheck(index string, query string) *ExpectedFTSpellCheck { + e := &ExpectedFTSpellCheck{} + e.cmd = m.factory.FTSpellCheck(m.ctx, index, query) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTSpellCheckWithArgs(index string, query string, options *redis.FTSpellCheckOptions) *ExpectedFTSpellCheck { + e := &ExpectedFTSpellCheck{} + e.cmd = m.factory.FTSpellCheckWithArgs(m.ctx, index, query, options) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTSearch(index string, query string) *ExpectedFTSearch { + e := &ExpectedFTSearch{} + e.cmd = m.factory.FTSearch(m.ctx, index, query) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTSearchWithArgs(index string, query string, options *redis.FTSearchOptions) *ExpectedFTSearch { + e := &ExpectedFTSearch{} + e.cmd = m.factory.FTSearchWithArgs(m.ctx, index, query, options) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTSynDump(index string) *ExpectedFTSynDump { + e := &ExpectedFTSynDump{} + e.cmd = m.factory.FTSynDump(m.ctx, index) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTSynUpdate(index string, synGroupId interface{}, terms []interface{}) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTSynUpdate(m.ctx, index, synGroupId, terms) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTSynUpdateWithArgs(index string, synGroupId interface{}, options *redis.FTSynUpdateOptions, terms []interface{}) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.FTSynUpdateWithArgs(m.ctx, index, synGroupId, options, terms) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectFTTagVals(index string, field string) *ExpectedStringSlice { + e := &ExpectedStringSlice{} + e.cmd = m.factory.FTTagVals(m.ctx, index, field) + m.pushExpect(e) + return e +} diff --git a/mock_ft_test.go b/mock_ft_test.go new file mode 100644 index 0000000..22a4cf3 --- /dev/null +++ b/mock_ft_test.go @@ -0,0 +1,139 @@ +package redismock + +import ( + "errors" + + . "github.com/onsi/gomega" + "github.com/redis/go-redis/v9" +) + +func operationAggregateCmd(base baseMock, expected func() *ExpectedAggregate, actual func() *redis.AggregateCmd) { + var ( + setErr = errors.New("aggregate cmd error") + val *redis.FTAggregateResult + err error + uninitalizedResult *redis.FTAggregateResult + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal(uninitalizedResult)) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal(uninitalizedResult)) + + base.ClearExpect() + expected().SetVal(&redis.FTAggregateResult{Total: 1}) + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal(&redis.FTAggregateResult{Total: 1})) +} + +func operationFTInfoCmd(base baseMock, expected func() *ExpectedFTInfo, actual func() *redis.FTInfoCmd) { + var ( + setErr = errors.New("FTInfo cmd error") + val redis.FTInfoResult + err error + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal(redis.FTInfoResult{})) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal(redis.FTInfoResult{})) + + base.ClearExpect() + expected().SetVal(redis.FTInfoResult{IndexName: "test"}) + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal(redis.FTInfoResult{IndexName: "test"})) +} + +func operationFTSpellCheckCmd(base baseMock, expected func() *ExpectedFTSpellCheck, actual func() *redis.FTSpellCheckCmd) { + var ( + setErr = errors.New("FTSpellCheck cmd error") + val []redis.SpellCheckResult + err error + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal([]redis.SpellCheckResult(nil))) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal([]redis.SpellCheckResult(nil))) + + base.ClearExpect() + expected().SetVal([]redis.SpellCheckResult{{Term: "test"}}) + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.SpellCheckResult{{Term: "test"}})) +} + +func operationFTSearchCmd(base baseMock, expected func() *ExpectedFTSearch, actual func() *redis.FTSearchCmd) { + var ( + setErr = errors.New("FTSearch cmd error") + val redis.FTSearchResult + err error + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal(redis.FTSearchResult{})) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal(redis.FTSearchResult{})) + + base.ClearExpect() + expected().SetVal(redis.FTSearchResult{Total: 5}) + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal(redis.FTSearchResult{Total: 5})) +} + +func operationFTSynDumpCmd(base baseMock, expected func() *ExpectedFTSynDump, actual func() *redis.FTSynDumpCmd) { + var ( + setErr = errors.New("FTSearch cmd error") + val []redis.FTSynDumpResult + err error + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal([]redis.FTSynDumpResult(nil))) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal([]redis.FTSynDumpResult(nil))) + + base.ClearExpect() + expected().SetVal([]redis.FTSynDumpResult{{Term: "test"}}) + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]redis.FTSynDumpResult{{Term: "test"}})) +} diff --git a/mock_json.go b/mock_json.go new file mode 100644 index 0000000..9d28c72 --- /dev/null +++ b/mock_json.go @@ -0,0 +1,185 @@ +package redismock + +import "github.com/redis/go-redis/v9" + +func (m *mock) ExpectJSONArrAppend(key, path string, values ...interface{}) *ExpectedIntSlice { + e := &ExpectedIntSlice{} + e.cmd = m.factory.JSONArrAppend(m.ctx, key, path, values...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONArrIndex(key, path string, value ...interface{}) *ExpectedIntSlice { + e := &ExpectedIntSlice{} + e.cmd = m.factory.JSONArrIndex(m.ctx, key, path, value...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONArrIndexWithArgs(key, path string, options *redis.JSONArrIndexArgs, value ...interface{}) *ExpectedIntSlice { + e := &ExpectedIntSlice{} + e.cmd = m.factory.JSONArrIndexWithArgs(m.ctx, key, path, options, value...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONArrInsert(key, path string, index int64, values ...interface{}) *ExpectedIntSlice { + e := &ExpectedIntSlice{} + e.cmd = m.factory.JSONArrInsert(m.ctx, key, path, index, values...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONArrLen(key, path string) *ExpectedIntSlice { + e := &ExpectedIntSlice{} + e.cmd = m.factory.JSONArrLen(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONArrPop(key, path string, index int) *ExpectedStringSlice { + e := &ExpectedStringSlice{} + e.cmd = m.factory.JSONArrPop(m.ctx, key, path, index) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONArrTrim(key, path string) *ExpectedIntSlice { + e := &ExpectedIntSlice{} + e.cmd = m.factory.JSONArrTrim(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONArrTrimWithArgs(key, path string, options *redis.JSONArrTrimArgs) *ExpectedIntSlice { + e := &ExpectedIntSlice{} + e.cmd = m.factory.JSONArrTrimWithArgs(m.ctx, key, path, options) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONClear(key, path string) *ExpectedInt { + e := &ExpectedInt{} + e.cmd = m.factory.JSONClear(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONDel(key, path string) *ExpectedInt { + e := &ExpectedInt{} + e.cmd = m.factory.JSONDel(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONForget(key, path string) *ExpectedInt { + e := &ExpectedInt{} + e.cmd = m.factory.JSONForget(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONGet(key string, paths ...string) *ExpectedJSON { + e := &ExpectedJSON{} + e.cmd = m.factory.JSONGet(m.ctx, key, paths...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONGetWithArgs(key string, options *redis.JSONGetArgs, paths ...string) *ExpectedJSON { + e := &ExpectedJSON{} + e.cmd = m.factory.JSONGetWithArgs(m.ctx, key, options, paths...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONMerge(key, path string, value string) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.JSONMerge(m.ctx, key, path, value) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONMSetArgs(docs []redis.JSONSetArgs) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.JSONMSetArgs(m.ctx, docs) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONMSet(params ...interface{}) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.JSONMSet(m.ctx, params...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONMGet(path string, keys ...string) *ExpectedJSONSlice { + e := &ExpectedJSONSlice{} + e.cmd = m.factory.JSONMGet(m.ctx, path, keys...) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONNumIncrBy(key, path string, value float64) *ExpectedJSON { + e := &ExpectedJSON{} + e.cmd = m.factory.JSONNumIncrBy(m.ctx, key, path, value) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONObjKeys(key, path string) *ExpectedSlice { + e := &ExpectedSlice{} + e.cmd = m.factory.JSONObjKeys(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONObjLen(key, path string) *ExpectedIntPointerSlice { + e := &ExpectedIntPointerSlice{} + e.cmd = m.factory.JSONObjLen(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONSet(key, path string, value interface{}) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.JSONSet(m.ctx, key, path, value) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONSetMode(key, path string, value interface{}, mode string) *ExpectedStatus { + e := &ExpectedStatus{} + e.cmd = m.factory.JSONSetMode(m.ctx, key, path, value, mode) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONStrAppend(key, path, value string) *ExpectedIntPointerSlice { + e := &ExpectedIntPointerSlice{} + e.cmd = m.factory.JSONStrAppend(m.ctx, key, path, value) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONStrLen(key, path string) *ExpectedIntPointerSlice { + e := &ExpectedIntPointerSlice{} + e.cmd = m.factory.JSONStrLen(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONToggle(key, path string) *ExpectedIntPointerSlice { + e := &ExpectedIntPointerSlice{} + e.cmd = m.factory.JSONToggle(m.ctx, key, path) + m.pushExpect(e) + return e +} + +func (m *mock) ExpectJSONType(key, path string) *ExpectedJSONSlice { + e := &ExpectedJSONSlice{} + e.cmd = m.factory.JSONType(m.ctx, key, path) + m.pushExpect(e) + return e +} diff --git a/mock_json_test.go b/mock_json_test.go new file mode 100644 index 0000000..72277fb --- /dev/null +++ b/mock_json_test.go @@ -0,0 +1,60 @@ +package redismock + +import ( + "errors" + + . "github.com/onsi/gomega" + "github.com/redis/go-redis/v9" +) + +func operationJSONCmd(base baseMock, expected func() *ExpectedJSON, actual func() *redis.JSONCmd) { + var ( + setErr = errors.New("JSON cmd error") + val string + err error + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal("")) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal("")) + + base.ClearExpect() + expected().SetVal("test") + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal("test")) +} + +func operationJSONSliceCmd(base baseMock, expected func() *ExpectedJSONSlice, actual func() *redis.JSONSliceCmd) { + var ( + setErr = errors.New("string slice cmd error") + val []interface{} + err error + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal([]interface{}(nil))) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal([]interface{}(nil))) + + base.ClearExpect() + expected().SetVal([]interface{}{"redis", "mock"}) + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]interface{}{"redis", "mock"})) +} diff --git a/mock_test.go b/mock_test.go index 0be8c7d..02519d7 100644 --- a/mock_test.go +++ b/mock_test.go @@ -312,6 +312,32 @@ func operationIntSliceCmd(base baseMock, expected func() *ExpectedIntSlice, actu Expect(val).To(Equal([]int64{1, 2, 3, 4})) } +func operationIntPointerSliceCmd(base baseMock, expected func() *ExpectedIntPointerSlice, actual func() *redis.IntPointerSliceCmd) { + var ( + setErr = errors.New("int slice cmd error") + val []*int64 + err error + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal([]*int64(nil))) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal([]*int64(nil))) + + base.ClearExpect() + expected().SetVal([]*int64{}) + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal([]*int64{})) +} + func operationScanCmd(base baseMock, expected func() *ExpectedScan, actual func() *redis.ScanCmd) { var ( setErr = errors.New("scan cmd error") @@ -1717,6 +1743,38 @@ func operationMapStringInterfaceCmd(base baseMock, expected func() *ExpectedMapS })) } +func operationMapMapStringInterfaceCmd(base baseMock, expected func() *ExpectedMapMapStringInterface, actual func() *redis.MapMapStringInterfaceCmd) { + var ( + setErr = errors.New("map map string interface cmd error") + val map[string]interface{} + err error + ) + + base.ClearExpect() + expected().SetErr(setErr) + val, err = actual().Result() + Expect(err).To(Equal(setErr)) + Expect(val).To(Equal(map[string]interface{}(nil))) + + base.ClearExpect() + expected() + val, err = actual().Result() + Expect(err).To(HaveOccurred()) + Expect(val).To(Equal(map[string]interface{}(nil))) + + base.ClearExpect() + expected().SetVal(map[string]interface{}{ + "key1": "val1", + "key2": 2, + }) + val, err = actual().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(Equal(map[string]interface{}{ + "key1": "val1", + "key2": 2, + })) +} + func operationTSTimestampValueSliceCmd(base baseMock, expected func() *ExpectedTSTimestampValueSlice, actual func() *redis.TSTimestampValueSliceCmd) { var ( setErr = errors.New("ts timestamp value slice cmd error")