Home > front end >  Junit Test case for applicationContext.getBean(class) returning null
Junit Test case for applicationContext.getBean(class) returning null

Time:10-09

When trying to write test case for applicationContext.getBean(classname). Getting null pointer exception. Below is the Java class

@Service
@Slf4j
public class MyClassName {

  @Autowired
  ServiceOne serviceOne;

  @Autowired
  ApplicationContext applicationContext;


  public getCitizenData(String mobileNumber) {

    CitizenDataService citizenDataService = applicationContext.getBean(CitizenDataService.class, mobileNumber);
    log.info("Getting Data");
    return citizenDataService.searchMethod(mobileNumber)
         // While debugging test file citizenDataService is coming as Null Hence getting Null Pointer exception
        .flatMap(.............
         )

Test File


class MyClassNameTest {

  private MyClassName mockMyClassName;

  @BeforeEach
  void setUp() {
    mockMyClassName = new MyClassName();
    mockMyClassName.serviceOne = mock(ServiceOne.class);
    mockMyClassName.applicationContext = mock(ApplicationContext.class);
    //mockMyClassName.applicationContext.getAutowireCapableBeanFactory();
  }

  @Test
  void testGetCitizenData() {
    // Setup
    // Configure ApplicationContext.getBean(...).
    final CitizenDataService citizenDataService = new CitizenDataService("mobileNumber");
    when(mockMyClassName.applicationContext.getBean(CitizenDataService.class, "args"))
        .thenReturn(citizenDataService);

    final result = mockMyClassName.getCitizenData("mobileNumber");
    // While debugging this citizenDataService is coming as Null Hence getting Null Pointer exception

How to write test case for this ?

CodePudding user response:

I think, application context is not set-up yet. The following code makes sure that the context has been set-up successfully.

If you use JUnit5, then automatic injection happens for application-context and still you can use '@Autowired' annotation to field inject that.

@SpringBootTest
class Test {
    @Test
    void contextLoads(ApplicationContext context) {
        assertThat(context).isNotNull();
    }
}

CodePudding user response:

It is because you stub the incorrect arguments on the getBean() on the mocked ApplicationContext . When a method on a mock is called but there are no matching stubbed arguments , it will return either null or an empty collection , or 0 for an int/Integer and false for a boolean/Boolean by default . So in you case NULL CitizenDataService is returned.

Changing the following should fix your problem :

 when(mockMyClassName.applicationContext.getBean(CitizenDataService.class, "mobileNumber"))
    .thenReturn(citizenDataService);

Another way is not to mock the ApplicationContext but use spring test to really start up the spring container which include the beans there are required for the test case :

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {MyClassName.class,ServiceOne.class,CitizenDataService.class})
public class MyClassNameTest {

     @Autowired
     private MyClassName myClassName
  

      @Test
      void testGetCitizenData() { 

     }

}

This will be slower than the plain Mockito approach because it needs more time to start up the spring container and also require you to manage what beans to be included in the context.

For me , I would refactor your class such that it does not require to autowire ApplicationContext into it and then write a plain Mockito test. It is not a good practise to get the bean from the ApplicationContext manually which will make your class coupled to the spring framework codes.

  • Related