I have a Java test class setup with Mockito and get some strange behavior. My class looks as follows:
@ExtendWith(MockitoExtension.class)
public class FrameworkTest {
@Mock private OrderService orderService;
@InjectMocks private CompanyService companyService;
@Test
void testexecuteOrder() {
Mockito.when(orderService.executeAuftrag((OrderData) Mockito.any()))
.thenReturn(OrderAnswer.builder().successful(true).build());
Output output = companyService.execute();
// ...
}
}
The method orderService.executeAuftrag()
is overloaded, only one method has as parameter OrderData
, so I have to cast Mockito.any()
to make it work.
Now my intuition is that company.execute()
is executed with the orderService
Mock and returns a successful OrderAnswer
when the method executeAuftrag
is called with OrderData (since I mocked it that way).
And that is actually what happens. Some of the times. Some other times - executing the exact same code without changes - the method executeAuftrag()
returns a null
object, making my test fail, because in the following line in CompanyService, a NPE is produced.
I find it very confusing that the exact same code without any changes sometimes does what it is expected to do and sometimes returns a null
where it is supposed to return a OrderAnswer
object.
Am I missing something?
Maybe I am using the wrong methods for mocking? Maybe there is some state saved between tests that I don't see?
My Mockito version is
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.12.4</version>
<scope>test</scope>
</dependency>
I use org.junit.jupiter:junit-jupiter-api:5.10.1
.
Just found the problem. Posting it here since the behavior is kind of interesting and other people might have the same problem.
The problem was the following:
OrderService
is an interface - the mocking here was correct. But the implementation OrderServiceImpl
was also mocked:
@Mock private OrderService orderService;
@Mock private OrderServiceImpl orderServiceImpl;
The names of the variables in my case were not as obvious as above so I overlooked it. After removing the Mock of the implementation, it works exactly as it should.
Interesting to me that there is no warning by Mockito when you mock an interface and the implementation for it. Also interesting that it sometimes worked and sometimes didn't - that made it really difficult to analyze.
Thanks for the comments which helped me finding the solution.