golang / mock

GoMock is a mocking framework for the Go programming language.
Apache License 2.0
9.3k stars 610 forks source link

Feature Request: allow a mock controller to be re-used #541

Open ethanpailes opened 3 years ago

ethanpailes commented 3 years ago

Requested Feature

It would be nice to have a way to re-use a mock controller across multiple different tests. Currently, the docs for Controller have this to say on the subject, "Each test should create a new Controller and invoke Finish via defer." and the docs for Finish drive the point home further with "It is not idempotent and therefore can only be invoked once." I have some thoughts on the API that could be provided for this, but I would be happy with anything that allows controller re-use.

Why is this needed?

Right now I have a test suite that stands up a server to place under test, injecting a bunch of mocks for external dependencies in the process. It then executes a number of lighter weight tests against the same server. Standing up a new server for each test would slow things down significantly, and I'd like to avoid it if at all possible. Right now, I call Finish on my mock controller at the end of the test suite, which, somewhat surprisingly, has worked out pretty well so far, but I'm now starting to see issues where the expectations from one test are interfering with the expectations from another test.

Proposed Solution

I think it would be cool if there was some way to ask the Controller for a handle that you could use for mocking for the duration of a single test. This handle can do two things:

I think it would make sense to generate an error if someone ever calls mock.EXPECT()... when there is an outstanding handle that has not yet been Finished. This would prevent errors because you put the expectation in the wrong place by accident.

Alternative Approaches

At first, I was thinking it could make sense to just have an alternative Finish method that would reset the expectation set and allow itself to be called multiple times, but I think this approach is problematic since it basically guarantees that the tests will have to be run serially.

Maybe instead of EXPECTIN the handle could allow you to look up a modified mock struct. Both approaches feel clunky to me, but this one feels clunkier than EXPECTIN.

What I'm looking for with this issue

I realize that this is a fairly big ask, so while I would of course be thrilled to have it implemented, I'm not expecting anything. I would like feedback on whether you think this is a reasonable feature and an indication about whether or not you might accept patches for this feature.

codyoss commented 3 years ago

Hey @ethanpailes, I think this issue has been discussed in the past. See #459.

ethanpailes commented 3 years ago

@codyoss that thread does seem like it is discussing exactly my pain point, sorry I missed it when searching the issue tracker.

It seems like that thread ended up closing due to issues with the proposed Continue interface. In addition to the issues raised in that thread, I see another issue which is that there is no way to allow parallel tests making use of that interface since they may interleave their EXPECTations and Continues.

That said, I think that the interface I proposed in this thread has a good solution to the wrong-testing.T problem (just pass the right testing.T value into the handle construction mehtod), and allows a thread safe implementation for parallel tests.

Do you want me to close this thread and comment on #459 or can we continue the discussion here?