我正在用JUnit和Mockito编写单元测试。让我们说我有以下测试课程:
@Mock(name="myService")
private myServiceClass myService;
@InjectMocks
private myClassIWantToTest classUnderTest;
final myModelClass myModel = new myModelClass();
@Before
private void setUp(){
MockitoAnnotiations.initMocks(this);
}
@Test
private void testSomething(){
myModel.setCode("someCode");
final MyDataClass myData = new MyDataClass();
myData.setCode("someCode");
doReturn("someCode").when(myModel.getCode());
doReturn(myModel).when(myService.getModelByCode("someCode"));
assertEquals(classUnderTest.getDataByCode(eq("someCode")), myData);
verify(myService.getModelByCode(eq("someCode")), atLeastOnce());
}
我的getDataByCode
方法classUnderTest
将模型转换为数据,它应该具有相同的代码。对我来说有点模糊的是,单元测试应该封装来自所有依赖项的classUnderTest
。但现在我有一个问题。我使用setter方法myData
和myModel
来设置值。问题是我为DoReturn
添加myModel
,但问题是,它不是注入的模拟。我尝试测试的方法很遗憾没有字段,它在方法中初始化,所以我无法真正解决它。
主要的是,当例如myModel
的设定者不再工作时,我的测试如上所示,将不再起作用。我想我有三个问题:
我需要多大程度的隔离测试类?我不需要将setter用于assertEquals吗?
还有另一种处理对象的方法,这些对象是在我想测试的方法中初始化的吗?处理此事的最佳方法是什么?
另外,构建这个的好模式是什么?我目前在测试方法中初始化我期望的myData结果。问题是这是一个相当简短的例子,但是我有一些课程,我有很多对象和方法。
答案 0 :(得分:1)
听起来你的主要问题是你要测试的类的设计。但之前有一些事情:
myModel.setCode("someCode");
doReturn("someCode").when(myModel.getCode());
这没有意义。这不是模拟,所以......在这里没有意义。如果它是一个模拟器,调用setter将毫无用处。
assertEquals(classUnderTest.getDataByCode(eq("someCode")), myData);
也很奇怪。你想调用getDataByCode,为什么eq
?做吧。叫它。写:
assertEquals(classUnderTest.getDataByCode("someCode"), myData);
Mockito-Matchers在您想要验证某些内容时很好,但通常您不会将它们用作实际方法调用的参数。
verify(myService.getModelByCode(eq("someCode")), atLeastOnce());
这段代码真的可以编译吗?不应该......
verify(myService, atLeastOnce()).getModelByCode(eq("someCode"));
因此,尽可能实际隔离单元测试是个好主意。您参与测试的外部问题越少,测试就越好。
我试图测试的方法很遗憾没有一个字段,它 在方法中初始化这个,所以我无法真正解决它。
这听起来像是一种代码味道,但如果没有相关的实际代码,很难说......