javamockingmockito

Test case throwing NPE when calling mocked method


I am trying to write a Mockito test class to cover some db interaction. The test case I am writing is supposed to return a stub response when the database call is invoked, but it's throwing an NPE trying to actually build a database connection.

Here is the method I am trying to test:

public class AdultDayCenterDBHandler extends DBTemplate implements AppConstants {
    Logger logger = LogManager.getLogger(AdultDayCenterDBHandler.class);    
    public List<FacilityEntity> retrieveAllAdultDayCenterFacilities(FacilitySearchCriteriaInf adcSearchCriteria) throws AdultDayCenterException
        {
            //Retrieve all the adult day care facilities.
            logger.info("[retrieveAllAdultDayCenterFacilities]:[START]");
            String sqlQuery = prepareQuery((FacilitySearchCriteriaInf)adcSearchCriteria);
            
            SearchQuery searchQuery = new SearchQuery();
            searchQuery.setSqlQuery(sqlQuery);
            List<FacilityEntity> adcList;
            try {
                if(null != logger) logger.debug("Sending Executing SQL query : " + searchQuery.getSqlQuery());
                adcList = (List<FacilityEntity>) callDB((SearchQuery)searchQuery);
            } catch (DBException e) {
                throw new AdultDayCenterException("Error ocurred in AdultDayCenterDBHandler while calling DB",e);
            }
            
            logger.info("[retrieveAllAdultDayCenterFacilities]:[END]");
            return adcList;
            
        }

And here is the test case:

@ExtendWith(MockitoExtension.class)
public class AdultDayCenterDBHandlerTest {
    
    @Mock
    private DBTemplate dbTemplate;
    @Mock
    private DBUtil dbUtil;
    
    @InjectMocks
    private AdultDayCenterDBHandler dbHandler;
    
    @BeforeEach
    public void setUp() {
        assertNotNull(dbUtil);
        assertNotNull(dbTemplate);
    }
    
    @Test
    public void testRetrieveAllAdultDayCenterFacilities() throws Exception {
        //Setup
        
        List<FacilityEntity> facilityList = generateStubData();
        List<FacilityEntity> responseFromTest = null;
        ADCSearchCriteria adcSearchCriteria = generateSearchCriteria();
        
        Mockito.when(dbTemplate.callDB(any(SearchQuery.class))).thenReturn(facilityList);
        
        //Get Result Set
        responseFromTest = dbHandler.retrieveAllAdultDayCenterFacilities(adcSearchCriteria);
        
        //Assertions
        assertNotNull(responseFromTest);
        assertEquals(responseFromTest.get(0).getFacilityName(),facilityList.get(0).getFacilityName());
    }

    private List<FacilityEntity> generateStubData() {
        List<FacilityEntity> response = new ArrayList<FacilityEntity>();
        
        FacilityEntity entity = new FacilityEntity();
        entity.setFacilityName("Test Facility 1");
        entity.setLicenseId(123456);
        entity.setLocationAddressStreetNumber("1234");
        entity.setLocationAddressLine1("Main Street");
        entity.setLocationAddressCity("Mechanicsville");
        entity.setLocationAddressStateName("VA");
        entity.setLocationAddressZipCode("23116");
        entity.setLocationCountyFips("51085");
        entity.setLocationCountyDesc("Hanover");
        entity.setAdministratorFirstName("Jane");
        entity.setAdministratorSurname("Doe");
        entity.setAdministratorTitle("Administrator");
        entity.setBusinessPhoneNumber("804-301-2011");
        entity.setClientCode("2101");
        
        response.add(entity);
        
        return response;
    }
    
    private ADCSearchCriteria generateSearchCriteria() {
        ADCSearchCriteria criteria = new ADCSearchCriteria();
        
        criteria.setFacilityName("Test Facility 1");
        criteria.setProgramCode(PROGRAM_CODES.ADC_F);
        
        return criteria;
    }
}

My guess is I need to mock an additional object, but I'm not sure why this line:

Mockito.when(dbTemplate.callDB(any(SearchQuery.class))).thenReturn(facilityList);

//Get Result Set
responseFromTest = dbHandler.retrieveAllAdultDayCenterFacilities(adcSearchCriteria);

isn't returning the mock object I defined. It's throwing an NPE trying to instantiate DBUtil.


Solution

  • I may be reading this incorrectly, but you mock an instance of DBTemplate. However, the class you're injecting mocks in doesn't contain any DBTemplate, it extends DBTemplate. In other words, your mocked object never goes into the AdultDayCenterDBHandler instance.

    If you want to mock the callDB call of the AdultDayCenterDBHandler instance, you need to create a spy. You can then mock the method call. However, you can't use "when(...).then(...)" because that will already call the actual method. Use the following instead:

    Mockito.doReturn(facilityList).when(dbHandler).callDB(any(SearchQuery.class));
    

    This way, the method call (callDB) is performed on an object representing the spied object, not the spied object itself.