Null Pointer on an Autowired Bean Which Is Not Mocked by Mockito

Null pointer on an autowired bean which is not mocked by mockito

Usually when unit testing you want to mock all external dependencies of a class. That way the unit test can remain independent and focused on the class under test.

Nevertheless, if you want to mix Spring autowiring with Mockito mocks, an easy solution is to annotate with both @InjectMocks and @Autowired:

  @InjectMocks
@Autowired
private UploadServiceImpl uploadService;

The net effect of this is that first Spring will autowire the bean, then Mockito will immediately overwrite the mocked dependencies with the available mocks.

Autowired fields of mocked object returns null in Mockito

You need to use the @InjectMocks annotation in your unit test :

@ExtendWith(MockitoExtension.class)
class StudentServiceTest {

@Mock
private StudentInstitutionMapper studentInstitutionMapper;

@InjectMocks
private StudentService studentService;

@Test
public void testStudentService_getPresentStudentCount1() {


StudentParams studentParam = mock(StudentParams.class);

Integer institutionTestId = 3539;
when(studentParam.getInstitutionTestId()).thenReturn(institutionTestId);


int i = studentService.getPresentStudentCount(studentParam);
assertEquals(0, i);

}
}

You should also configure the behavior of the studentInstitutionMapper in the unit test to make it return the expected result.

Mocking a autowired bean throws a NullPointerException

Because you are using Spring controller, you need to import your controller from SpringContext, by @Autowired annotation:

@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
@SpringBootTest
public class MyControllerTest {
@MockBean
private ServiceA serviceA;

@Autowired // import through Spring
private MyController myController;

@Before
public void init() {
when(serviceA.getCurrentUser()).thenReturn(some object);
}

@Test
public void firstTest() {
myController.handleMessage(); // ---> Throws NPE stating that serviceA is null
}
}

@MockBean are added to SpringContext, so they will be injecte as a dependency to your controller.

Mockito Injecting Null values into a Spring bean when using @Mock?

For me it's unclear how the combination of Spring and Mockito as you took it from the referenced blog source should work at all as expected. At least I may explain your observation:

  • Your test (this.mockMvc.perform()) is working on the web application context created by Spring. In that context ProductController was instantiated by Spring (context:component-scan). The productService was then autowired with the Mockito mock you created in mvc-dispatcher-servlet.xml as someDependencyMock.
  • If you inject the mockproductService via @Autowired, Spring injects the someDependencyMock instance from its context. So your Mockito.when() call works correctly on this instance, which was already correctly wired to the ProductController as mentioned before.
  • But if you inject the mockproductService via @Mock, Mockito injects a new instance of ProductService, not the one of the Spring context, since it knows nothing about Spring at all. So your Mockito.when() call does not operate on the mock which was autowired by Spring and thus someDependencyMock stays uninitialized.

So what's left unclear for me about how the original code from the blog worked at all is:

  • The productController property annotated with @InjectMocks will be initialized by Mockito and even correctly wired to the mockproductService in the test class. But Spring does not know anything about that object and won't use it in this.mockMvc.perform() calls. So I assume if you inject mockproductService only with @Autowired your test works as intended even if you delete both the productController property and the MockitoAnnotations.initMocks() call in your test class.


Related Topics



Leave a reply



Submit