mockito
mockito copied to clipboard
Seemingly random java.lang.AssertionError in MockUtil.getMockHandlerOrNull
Hi, we're experiencing an issue very similar to #2793 where some tests fail with an assertion error:
java.lang.AssertionError
at org.mockito.internal.util.MockUtil.getMockHandlerOrNull(MockUtil.java:160)
.....
The issue started occuring in some of our tests after upgrading to mockito 5.12.0 where "inline" became the default for the mock maker. In some tests similar to the attached example we have mocks that have to be created using SUBCLASS and to make these tests pass we have to swich all mocks to SUBCLASS. It seemed a bit "code-smelly" during code review so here I am...
I've spent some time trying to prepare a piece of code that would fail each time - see attached example mockito-issue.zip
It's a simple spring-mvc controller test, perform a mvn clean install to run it.
What I've discovered so far:
- The test works every time when using java 17.0.10-jbr from sdkman
- The test fails every time when using 17.0.12-tem from sdkman
Then, while using the "failing" 17.0.12-tem java I noticed that making ANY of the following changes makes the tests pass:
- Removing
SomeControllerTest.tearDownmethod (which is empty!) - Removing any of the
thirdDependency*bean definitions fromSomeControllerTestContext(so reducing the number of mocks in the spring context from 16 to 15) - Switching the MockMaker from SUBCLASS to INLINE in
SomeControllerTestContext.secondDependency
I have the same issue with mockito 4.11.0 and java11 (temurin and coretto 11.0.18)
I analyzed the Problem and tracked it down to
getMockHandlerOrNull
with the line
assert getMockMaker(handler.getMockSettings().getMockMaker()) == mockMaker;
Assuming we have more than one Mockmaker in the mockMakers field, this line will seriously fail, if the Mockmakers themselves do not ensure only returning handlers of the same type as themselves. SubclassByteBuddyMockMaker does return any Handler of a mock and thus this line will fail.
I have similar issue as above, mockito 5.17, java11.
assert getMockMaker(handler.getMockSettings().getMockMaker()) == mockMaker;
We are using both inline and subclass mocks.
The issue in getMockHandlerOrNull happens when order of mockMakers is as follows:
Inline maker as second.
Both handlers mockMakers are null:
However mockMaker variable is of class ByteBuddyMockMaker and the assertion is raised.
When there is following order of mocks:
Inline mock first.
It works, but “by chance”.
Handlers are not null as before:
But, again, for both handlers mockmaker are null:
However in this scenario:
is Inline and assertion passes because default mockmaker is Inline:
The root cause is (probably) in Handler – whatever type of handler, its mockMaker is null leading to random failures (in current shape logic getMockHandlerOrNull works only ‘by chance’). Shouldn't mockMaker be set properly on handler when object is mocked or spied? @TimvdLippe could you have a look? You've fixes similar issue in https://github.com/mockito/mockito/issues/2823
Had this issue, too, in Quarkus context, which uses inline MockMaker by default. I had some tests, which created mocks with SUBCLASS:
Mockito.withSettings().mockMaker(MockMakers.SUBCLASS)
It randomly failed the whole test suite with the AssertionError above. I've rewritten the tests, to not use SUBCLASS, and it seems to be gone.