Here is the class I want to test:
public class MyClass {
private final MyService myService;
public MyClass(MyService myService) {
this.myService = myService;
}
public BigDecimal doSomething(Long id) {
MyEntity myEntity = myService.getEntity(id);
MySubEntity mySubEntity = myEntity.getSubEntity();
Long myId = mySubEntity.getId();
BigDecimal result = BigDecimal.ZERO;
// misc operations
return result;
}
}
And here is the test class:
@SpringBootTest
@ExtendWith(MockitoExtension.class)
@MockitoSettings
public class MyClassTests {
@Mock
private MyService myService;
@InjectMocks
private MyClass myClass;
@Test
public void testDoSomething() {
// GIVEN
MyEntity myEntity = mock(MyEntity.class);
MySubEntity mySubEntity = mock(MySubEntity.class);
BigDecimal result = new BigDecimal("3.1415926");
// WHEN
when(myService.getEntity(any())).thenReturn(myEntity);
when(myEntity.getSubEntity()).thenReturn(mySubEntity);
when(mySubEntity.getId()).thenReturn(42L);
// THEN
assertEquals(result, myClass.doSomething(36L));
}
}
Since myService is a data access layer, I create a mock of it and inject it into MyClass. Then I mock the objects returned by myService.getEntity() and myEntity.getSubEntity().
When I run this test, I get a NullPointerException. If I debug the MyClass class, I find that my myEntity variable is null despite being mocked, and yet the mock is returned in the first line of the WHEN.
It is only set to null in the MyClass class. Inside the test, this variable correctly refers to a mocked MyEntity object.
Do you have any idea how I can fix this?
The problem came from the @SpringBootTest annotation, which I had forgotten to delete.
Thanks to @tgdavies and @Feel free for pointing out this oversight.