Open tommyalatalo opened 3 years ago
I can't test it right now, but I'm pretty sure testify lets you do this by providing different expecations:
tr.On("Scan", ctx, uint64(0), "first:*", int64(0)).
Return(redis.NewScanCmdResult([]string{}, uint64(0), test.err))
tr.On("Scan", ctx, uint64(0), "second:*", int64(0)).
Return(redis.NewScanCmdResult([]string{}, uint64(0), test.err))
Alternatively, you could use DoAndReturn()
if you wanted to handle the arguments dynamically.
I can't test it right now, but I'm pretty sure testify lets you do this by providing different expecations:
tr.On("Scan", ctx, uint64(0), "first:*", int64(0)). Return(redis.NewScanCmdResult([]string{}, uint64(0), test.err)) tr.On("Scan", ctx, uint64(0), "second:*", int64(0)). Return(redis.NewScanCmdResult([]string{}, uint64(0), test.err))
Alternatively, you could use
DoAndReturn()
if you wanted to handle the arguments dynamically.
I don't see any difference in the example mocks you defined here except for the path in redis?
Not sure what you wanted to point out with those two mocks, that's kind of another example of my problem, if you want to mock second
but not first
it doesn't seem to work to just omit the mock for first
.
I would be really interested in how you would use DoAndReturn()
to handle this case. The best, and preferred solution, I think would still be to have redismock strictly only mock the calls you define with .On()
, if it's not already doing that and I'm misunderstanding the way it works.
I see, I didn't understand you at first. I haven't tested these, but this should do what you want:
tr.On("Scan", ctx, uint64(0), mock.Anything, int64(0)).
Times(2).
DoAndReturn(func (ctx context.Context, cursor uint64, match string, count int64) *redis.ScanCmd {
if match == "second:*" {
return redis.NewScanCmdResult([]string{}, uint64(0), test.err)
}
return client.Scan(ctx, cursor, match, count)
})
Or, if you prefer to have separate expections:
tr.On("Scan", ctx, uint64(0), "first:*", int64(0)).
DoAndReturn(client.Scan)
tr.On("Scan", ctx, uint64(0), "second:*", int64(0)).
Return(redis.NewScanCmdResult([]string{}, uint64(0), test.err))
I tried to use this one of your examples:
tr.On("Scan", ctx, uint64(0), "first:*", int64(0)).DoAndReturn(client.Scan)
This can't be done though, because `type *mock.Call has no field or method DoAndReturn?
Sorry, I got my mocking frameworks mixed up. Unfortunatly, testify mock package doesn't have a way to dynamically return, but a quick search brought this up: https://github.com/stretchr/testify/issues/350 which will solve your problem.
I'm having problems with redismock catching other calls for the same operation, which shouldn't be mocked.
For instance, I have a function where I call
Scan
two times, and I only want to mock the second call to simulate an error being returned. This seems to not work since redismock thinks it should mock the firstScan
call as well, even though the key has not been set up to be mocked.An example in code:
Now if I mock the second call in my test suite like this:
redismock will return this error:
I'm using NewNiceMock to create my test client. Is there a way to set the mocking to be stricter, so that any calls that are not defined with the
.On
function will be completely ignored and not fuzzy-matched or whatever is happening here now?The behavior that I'm getting now is requiring me to mock both calls, which means that the first call can't use miniredis to get real data, which is of course not desirable.