我正在用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());
}
我的classUnderTest
中的方法getDataByCode
将Model转换为Data,它应该具有相同的代码。对我来说有点模糊的是,单元测试应该封装来自所有依赖项的classUnderTest
。但现在我遇到了一个问题。我使用setter方法myData
和myModel
来设置一个值。问题是我为myModel
放了一个DoReturn
,但问题是,它不是一个注入的Mock。不幸的是,我尝试测试的方法没有字段,它在方法中初始化了这个字段,所以我无法真正解决它
最重要的是,当myModel
的setter不再工作时,如上所示的测试将不再工作。我想我有三个问题:
隔离测试类需要多大的难度?我不需要使用assertEquals的setter吗?
有没有其他方法可以处理在我想要测试的方法中初始化的对象?处理这样一件事的最佳方法是什么?
此外,构建这种结构的好模式是什么?我当前在一个测试方法中初始化了预期的myData结果。问题是,这是一个相当简短和简单的例子,但我在类中有大量的对象和方法。
听起来您的主要问题是要测试的类的设计。但之前有几件事:
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"));
因此,尽可能地隔离单元测试是个好主意。你在测试中遇到的外部问题越少,测试就越好。
不幸的是,我尝试测试的方法没有字段,它在方法中初始化它,所以我不能真正解决它
这听起来很像代码的味道,但如果没有真正的代码,很难说。。。