mock
mock copied to clipboard
Adding method to Controller allowing to check whether all expected calls have been made
I want to be able to check whether all expected calls have been made before Controller#Finish() gets invoked as the code being tested is running asynchronously and I can only approximate when all calls will have been made.
This addition should allow it to check whether all expected calls towards the mock(s) have been made in an idempotent way. This is useful when testing asynchronous/non-deterministic things that aren't fully under the developers control (e.g., in end-2-end tests).
If necessary I can elaborate on my specific testing scenario.
Having such a method allows the user to write something like
require.Eventually(t, mockCtrl.AllExpectedCallsSatisfied, 60*time.Second, 100*time.Millisecond)
instead of having to wait for an approximated amount of time (which slows down the tests unnecessarily) in order to make sure all expected calls have been satisfied before Controller#Finish() gets invoked.
Why is this needed? Because right now AFAIU I have to add a sleep for an amount of time I approximate to be enough for my system to be done with its work. This is not nice for several reasons:
- It's dangerous because my estimation could be too little and calls have not been made at that point
- It's slow because I basically have to approximate very conservatively due to the problem described above
In order to check how feasible the implementation would be I already coded a proposal that I would be happy to open a PR for: https://github.com/golang/mock/compare/main...FlorianLoch:check-expectation-fulfilled?expand=1
This issue (and the linked PR) ist open for more than 9 months now. Could I please get some official feedback? That would be nice :)
Have you considered to use a WaitGroup as described in https://medium.com/@poy/gomock-and-go-routines-6a7c01d989d5 for signalling completion. I know it is actually a bit more difficult since you also need to unlock your waiting test thread on failures, if you do not want to timeout, which totally disturbs the user experience.
That isn't a bad idea as a work around - but I guess having this addition in place would be simpler and more intuitive.
It's a little disappointing, that there is no actual activity on this issue and the related PR 🤷
Here is a different use case for this feature that I would really like support for. Suppose I have this code I want to test:
type Callback interface {
Callback(int)
}
func PerformCallback(cb Callback, par int) {
cb.Callback(par)
}
Then I would like to do it like this:
func TestPerformCallback(t *testing.T) {
ctrl := gomock.NewController(t)
cb := NewMockCallback(ctrl)
cb.EXPECT().Callback(1)
PerformCallback(cb, 1)
// Here it would be nice to assert that all expectations setup so far have been met
cb.EXPECT().Callback(2)
PerformCallback(cb, 2)
}