我有这种方法进行单元测试:
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;
}
}
测试类是:
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);
}
}
很明显,SUT方法失败了:
Long dpId = savedDPModel.getDpId();
因为在SUT方法中创建的实例与我们想要在dpDaoMock
中使用的实例不同。
那我怎么能克服这个问题呢?还有其他更好的方法来模拟DAO吗?
由于
答案 0 :(得分:1)
一些选项。
DPModel
的工厂界面可以作为DPService
的依赖项引入。这样,工厂方法(工厂的)的返回值可以被模拟并用于断言。
Mockito匹配器可用于检查模拟方法的参数:
Mockito.when(dpDaoMock.save(Matchers.any())).thenReturn(dpModel2);
或更严格的例子:
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);