user1539343 user1539343 - 1 month ago 6
Java Question

Mockito and unit testing - how to control new object creation

I have this method to be unit tested:

public class DPService {
public DPModel saveTreeRecursively(DPDTO dpDTO) {
DPModel dpModel = new DPModel(dpDTO.getDPKey(), dpDTO.getName());
DPModel savedDpModel = dpDAO.save(dpModel);
Long dpId = savedDPModel.getDpId();

// after some operations
return savedDpModel;
}
}


The test class is:

public class DPServiceTest {
@Test
public void testSaveTreeRecursively() {
DPModel dpModel1 = new DPModel(dpKey, dpName); // same dpKey and dpName
//used in the SUT method to create DPModel, dpModel

DPModel dpModel2 = new DPModel(dpKey, dpName);
dpModel2.setDPId(123L);

// SUT
DPService dpService = new DPService();

// creating a mock DAO so that, the unit testing is independent of real DAO
DPDaoMock dpDaoMock = Mockito.mock(DPDao.class);

// we want to control the mock dpDAO so that it returns
// the model we want that the below SUT method uses; basically we are pretending that
// the dpDAO saved the dpModel1 with a primary key, dpId = 123
// and returned the dpModel2 saved in the database.
Mockito.when(dpDaoMock.save(dpModel1)).thenReturn(dpModel2);

DPModel dpModel3 = dpService.saveTreeRecursively(dpDTO);

assertEquals(dpModel3.getDpID(), 123L);
}
}


So obviously the SUT method failed at line:

Long dpId = savedDPModel.getDpId();


because the instance created inside the SUT method is not the same one we want to be used from the
dpDaoMock
.

So how can I overcome this problem? Is there any other better approach to mock DAO?

Thanks

Answer

Some of the options.

Abstract factory

The factory interface of DPModel can be introduced as a dependency of DPService. So that, the return value of the factory method (of the factory) can be mocked and used for the assertion.

Please refer to the Abstract factory pattern.

Matcher

Mockito matchers can be used to check arguments of mock methods:

Mockito.when(dpDaoMock.save(Matchers.any())).thenReturn(dpModel2);

or more strict example:

Mockito.when(dpDaoMock.save(Matchers.argThat(new ArgumentMatcher<DPModel>() {
    @Override
    public boolean matches(Object argument) {
        DPModel dpModel = (DPModel) argument;
        return dpModel.getDpId().equals(123L);
    }
}))).thenReturn(dpModel2);
Comments