-
Notifications
You must be signed in to change notification settings - Fork 38.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Offer a way for MockitoTestExecutionListener
to enable strict stubbing
#33318
Comments
This feature is still being debated by the community in mockito/mockito#769, and I'm not sure we're in a position to force that choice right now on the Spring Boot community. Looking at the comments in that issue, it seems that some developers had issues while applying this to their projects; arguable, some of those might be linked to their setup or even bad practices. If we do consider that change, we should do that in a proper milestone and document that change properly. I'm marking this issue for team attention and we'll discuss this. In the meantime @jschmied, don't hesitate to point us to official Mockito documentation/best practices about this feature. |
The discussion you are refering ist ourdated. Since Mockito 2.+, strict stubbing is used by default when initializing our mocks using either of:
Spring ist using Mockito.initMocks() instead of Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking(); what is causing this problem. See: https://www.baeldung.com/mockito-unnecessary-stubbing-exception So by default (We are at Mockito 2.23 in Spring Boot 2.1) all plain JUnit test use strict stubbing by default but all Sprint tests do not. This behaviour is inconstent and anoying. Of course, enabling it would possibly force users to clean up their spring tests. All plain JUnit test had to be cleaned up with switch to spring boot 2.x already. It would be nice to be able it at least by some property or annotation (or in my oppinon, better switch it on and give user the possibility to disable it easily) |
As far as I can tell, the issue to which @bclozel linked remains accurate. |
I have seen nobody using Fact is: if you have two JUnit test, one with @RunWith(MockitoJUnitRunner.class) one with @RunWith(SpringRunner.class)
@SpringBootTest() the first one will fail when there are unnecessary stubs (default is STRICT), the second one will pass. You can test easily. |
On further inspection, as far as I can tell, Mockito does not use I think we could safely switch to |
This would be nice. I usually run JUnit from eclipse first and unused stubs make the tests failing in the IDE. I did not test this as part of maven build on Jenkins. So you might be right. |
@jschmied Could you share some example tests with us please? It would be useful to see exactly what you are seeing and to confirm that Mockito's behaviour matches its documentation. |
Sure. @RunWith(MockitoJUnitRunner.class)
public class TestJUnit {
@Test
public void test1() {
List<Object> list = mock(List.class);
when(list.get(anyInt())).thenReturn(new Object());
}
} This one passes: @RunWith(SpringRunner.class)
@SpringBootTest
public class TestSpring {
@Test
public void test1() {
List<Object> list = mock(List.class);
when(list.get(anyInt())).thenReturn(new Object());
}
} Only the annotations on top differ |
Thank you, @jschmied. I can see now that I was wrong before. Sorry. Mockito does fail by default when using The concept of strictness differs between the runner and the rule. There are three variants of the runner:
There are three variants of
The An equivalent of the |
I think there's currently too much risk in changing our defaults at this point. The As soon as the Mockto team decide that The only problem that we see with our current approach is that we don't offer a good way to change the defaults for an individual test. I think we should investigate offering a way to switch the strictness for an individual test. |
+1. It would be nice if we could change the strictness used in a test. Even better if you could support |
Indeed, it took me a while to understand why my unit and integration tests were behaving differently, and noticing that @AfterEach
void afterEach() {
// Only stubbed (or otherwise expected) calls allowed.
ignoreStubs(/* explicit list of mockbeans here */);
verifyNoMoreInteractions(/* the same list */);
} This is not really ideal (and does not provide the usual nice helpful errors for unnecessary stubbings). |
A workaround to manually set the strictness would help. |
@mminot-yseop A couple of remarks:
Due to these issues, I switched back to vanilla Mockito and its @mock and @Injectmocks annotations. |
Hum I was using this in conjunction with
I said so in my message, you know 😁 ↓
Yeah probably not perfect at all. |
A workaround to enable "strict stubs" in |
Since Spring Boot usually aligns with the defaults of technologies it integrates (and in some cases even maintains the tests that verify the alignment), what's the reason not to do the same here? Having substantially different behavior of mocks between tests set up with Mockito's own facilities (for example, |
There are three different ways to do things with Mockito. In addition to |
That’s an interesting point. However, this issue, I think, is not exactly about the default behavior but mostly about the lack of simple, built-in way to switch to the “strict” mode in a Boot test, and therefore remains valid IMHO. Sidenote: I kinda fail to see in which contexts it can be interesting not to be strict. 🤔 (But I’m no expert of course, just your average user.) The most extreme cases I saw so far were tests with at most one or two annoying mocks that are not-so-relevant to the things being tested (while still being relied upon here and there), but in such cases there’s still |
@mminot-yseop Apologies for the confusion. I was responding to @vpavic. We agree that this issue remains valid. It would have been closed if we thought otherwise. |
Sure 😄 No real confusion, I guess I was just being talkative.
Isn’t that the JUnit 4 way of doing things, though? I got the impression that nearly all modern-ish projects rely on v5, and therefore use |
@wilkinsona Sorry, but I disagree with your reasoning here. Mockito clearly documents (section 40. Improved productivity and cleaner tests with "stricter" Mockito) that:
From end user perspective, it shouldn't matter which way of configuring Mockito does Spring Boot use internally, but rather what Mockito's user-facing configuration facilities do. These days, JUnit Platform is the dominant unit testing framework and |
We're at risk of going round in circles here.
This ignores the risk that @philwebb has already described above. Minimising that risk requires a setting that allows the strictness to be configured. That's what this issue is tracking. |
Both this issue and the comment stating risks are 3+ years old now. In the meanwhile there has been no evidence that Mockito will stop favoring the strictness by default, quite the opposite. I think that should warrant re-evaluation of the goals of this ticket, which IMO should be to flip the default behavior and offer a way to disable strict stubbing. I'm aware that You don't have to take my word on this, since a very simple GitHub code search can easily show which approach is the more popular one:
That's an order of magnitude difference and I'd argue that the figures are even tilted to benefit the |
With @simonbasle can you please review the history of this issue? Perhaps a chance for us to consider this in some form for Spring Framework 6.2 still. |
I think we can use 6.2 as an opportunity to change Spring Framework's newly introduced I was not able to find a way to account for the @SpringJUnitConfig(Config.class)
@MockitoBeanSettings(Strictness.LENIENT)
public class MyIntegrationTests {
@Test
public void unusedStubbingNotReported() {
var list = Mockito.mock(List.class);
Mockito.when(list.get(Mockito.anyInt())).thenReturn(new Object());
}
} |
It's indeed unfortunate that
Yes, your proposal looks good. 👍 |
MockitoTestExecutionListener
to enable strict stubbing
This change remove the support for Mockito annotations, `MockitoSession` and opening/closing of mocks that was inherited from Boot's `@MockBean` support, as well as the switch to `MockitoSession` made in 1c893e6. Attempting to take responsability for things Mockito's own JUnit Jupiter extension does better is not ideal, and we found it leads to several corner cases which make `SpringExtension` and `MockitoExtension` incompatible in the current approach. Instead, this change refocuses our Mockito bean overriding support exclusively on aspects specific to the Framework. `MockitoExtension` will thus be usable in conjunction with `SpringExtension` if one needs to use `@Captor`/`@InitMocks`/`@Mock`/`@Spy` or other Mockito utilities. See gh-33318 Closes gh-33692
Unfortunately, we had to backtrack on this in 6.2.0-RC2 due to various blocking issues with |
Is there an issue that tracks the re-introduction of strict stubbing as the default behavior? |
There wasn't one, but there is now. 😉 |
Running tests with
SpringRunner
does not report unused stubs likeMockitoJUnitRunner
does.In
MockitoTestExecutionListener.initMocks
it should useto enable strict mocking.
The text was updated successfully, but these errors were encountered: