我有这个方法要进行单元测试:
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的方法?
谢谢
一些选项
<标题>抽象工厂h1>DPModel
的工厂接口可以作为DPService
的依赖引入。这样,(工厂的)工厂方法的返回值就可以模拟并用于断言。
请参考抽象工厂模式。
<标题>匹配器h1> 拟匹配器可以用来检查模拟方法的参数: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);
标题>标题>