Strictness in Mockito
See original GitHub issueIntroduction
This issue explores the addition of “strict” behavior and APIs to Mockito. Traditionally, Mockito is a lenient mocking framework. For background and motivation, check out Szczepan’s short article on LinkedIn or in-depth article on Mockito blog.
Why strictness in Mockito:
- productivity - improved debugging and writing tests. Currently MockitoHint warns about stubbing argument mismatches. Strict stubbing would promote the warning into an exception, making the test fail fast and improve debuggability / productivity.
- clean code - avoid unnecessary stubbings, test fails when unncessary stubs are present.
Concrete API proposals:
- “strict stubbing” proposal:
#770 - “strict mocking” proposal: #1097
- opt-out from strict stubbing at mock / method level: #792
Example exception message indicating subbing problem:
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'simpleMethod' method:
mock.simpleMethod(“Foo");
-> at … StrictStubbingEndToEndTest.java:101
- has following stubbing(s) with different arguments:
1. mock.simpleMethod(“foo");
-> at … StrictStubbingEndToEndTest.java:100
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
Details
Strictness in Mockito can have 2 forms:
- Strict stubbing that requires that all declared stubs are actually used
- Strict mocks, that require all non-void methods to be stubbed before they are called
Strictness behavior can be implemented as:
- warning on the console
- exception thrown
Strictness API can be implemented in:
- JUnit runner / rule
- TestNG runner
- explicit method to call by the user
Future direction:
- strict stubbing on by default, opt-out available
- strict mocking off by default, opt-in available
Implementation as of Mockito 2.2.x:
- JUnitRunner - fails at the end of test class when unused stubbings are present. Opt out available via JUnitRunner.Silent
- JUnitRule - warn at the end of test method about a) unused stubs b) stubs invoked with different arguments. Opt-out available via rule().silent().
Mockito 2.x proposal:
- New “strict stubbing” API for JUnit rule -
#770 - New Answer.StrictMock that fails immediately when non-void method invoked on without prior stubbing - #649
- new verifyStubs() method to use when rule/runner not in used
Mockito 3 proposal:
- strict stubbing is the default
- change behavior of verifyNoMoreInvocations()
- runner and rule behave the same
Issue Analytics
- State:
- Created 7 years ago
- Reactions:5
- Comments:54 (19 by maintainers)
Top Results From Across the Web
Strictness (Mockito 2.8.9 API) - Javadoc.io
Configures the "strictness" of Mockito during a mocking session. A session typically maps to a single test method invocation. Strictness drives cleaner ...
Read more >Mockito Strict Stubbing and The UnnecessaryStubbingException
+, Mockito has been introducing new features that nudge the framework towards “strictness.” The main goals behind this are:.
Read more >Mockito 3 Mocking Strictness - Junit 5 Jupiter | wesome.org
Mockito provides Strictness enum rules which need to be set in @MockitoSettings that enforce developers to remove unnecessary stubbing, unwanted mocks, ...
Read more >Setting the strictness of Mockito mock(s) - David Vlijmincx
Mockito has three levels of strictness, from none to strict stubbing, to help you write cleaner tests. The current default is to warn...
Read more >How to resolve Unneccessary Stubbing exception
... this annotation provided in mockito-junit-jupiter package: @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
While writing an integration test I came across a specific example where this Strictness may actually be useful. In this example, I want to explicitly mock a call to a service and ensure it is definitely called. I have, for example, the following method:
The two things I need to test here are:
uploadDirectory
called?I don’t extrinsically care whether
download
was called; it’s implied by the other two facts.To test this, I need something like the following:
The problem here is that there is no guarantee that
uploadDirectory
was ever called. There are three existing solutions to this:verify
Assert some flag is set
Obvious problem with this: it requires more code. It’s also not as succinct for describing what is happening.
Rely on Strict mode
This is the current solution. You called
when
. You should expect it to be called.Possible issues:
LENIENT
over the tests to expand them. It’s no longer verified.Verify
The most natural of the options, I want to explicitly verify that something happened. But for that, it need the following line:
Problem: duplicated code. Pretty obvious that that’s not ideal.
An alternative solution
What about instead of changing the API (which is what Strict-mode does; it means you have to change all your tests in some way), the API is expanded with an extra command:
when
but must be called at least onceverify
it accepts aVerificationMode
liketimes
when
no longer verifies that the stubbed method was calledThis would solve all the above issues. Non-mocked method calls could still throw an exception for missing stubbings (which does indicate a problem).
I think from a code maintenance point of view, “behavior: warning on the console” is not really useful - in such a case a CI system would not inform anyone about unused stubs. An exception would be a lot better.