[英]Verifying objects within a mocked object are passed into argument in Mockito
Question Context 问题背景
I have a wrapper class with two objects that contain a list. 我有一个包装器类,其中包含两个包含列表的对象。 (ie Class1 and Class2 both have a Widget List.) (即Class1和Class2都有一个小部件列表。)
public class WrapperClass {
Class1 class1;
Class2 class2;
}
I have a utils class which processes the Wrapper class 我有一个utils类,它处理Wrapper类
public class WrapperUtils {
public void processClasses() {
WrapperClass wrapperClass = getWrapperClass();
doSomething(class1.getWidgetList());
doSomething(class2.getWidgetList());
}
private WrapperClass getWrapperClass() {
return wrapperClassFromOnlineService;
}
public void doSomething(List<Widget> widgetList) {}
}
Goal 目标
I'd like to use Mockito to verify that the doSomething
method gets called with class1's widget list. 我想使用Mockito来验证doSomething
方法是否被class1的小部件列表调用。
My Attempt 我的尝试
@Test
public void main(String[] args) {
WrapperClass wrapperClass = new WrapperClass();
wrapperClass.class1 = new Class1();
wrapperClass.class2 = new Class2();
WrapperUtils utils = new WrapperUtils();
Mockito.when(utils.getWrapperClass()).thenReturn(wrapperClass);
Mockito.verify(utils, times(1)).doSomething(wrapperClass.class1.getWidgetList());
Mockito.verify(utils, times(1)).doSomething(wrapperClass.class2.getWidgetList());
}
Results of above code: doSomething registers as being called twice for both verify statements. 上面代码的结果:doSomething注册为两个verify语句两次被调用。 My guess is that the widget lists are treated as the same? 我的猜测是小部件列表被视为相同?
This code has a design issue that makes it difficult to test with mocks. 该代码具有一个设计问题,很难通过模拟进行测试。
What that mean is that 那是什么意思
Here's an idea of how I'd write the test, this code is mainly focused on interactions, but it is possible to focus the assertions on the state of Class
(don't mock them in this case !!!) : 这是我如何编写测试的一个想法,该代码主要集中于交互,但是可以将断言集中在Class
的状态上(在这种情况下,请不要嘲笑它们!):
@RunWith(MockitoJUnitRunner.class)
public class WrapperUtilsTest {
@Mock Class class1;
@Mock Class class2;
@Test public void ensure_that____whatever() {
// given
WrapperUtils tested_utils = new WrapperUtils(new WrapperClass(class1, class2));
// when
tested_utils.processClass();
// then
verify(class1).someInteraction();
verify(class2).someInteraction();
}
}
And the implementation could look like 实现看起来像
public class WrapperUtils {
private WrapperClass wrapperClass;
public WrapperUtils(WrapperClass wrapperClass) {
this.wrapperClass = wrapperClass;
}
public void processClasses() {
doSomething(wrapperClass.class1);
doSomething(wrapperClass.class2);
}
public void doSomething(Class clazz) {
clazz.someInteraction();
}
}
Note the wrapperClass
is injected in the WrapperUtils
via the constructor, that works but you can also pass a Supplier
(available in guava or in JDK8), this supplier could get the data from anywhere, a webservice for exemple. 请注意, wrapperClass
是通过构造函数注入WrapperUtils
,该函数可以工作,但您也可以传递Supplier
(在guava或JDK8中可用),此Supplier可以从任何地方获取数据,例如Web服务。 Or it could your type. 也可以是您的类型。 In the test the supplier would be a mock. 在测试中,供应商将是一个模拟。
@RunWith(MockitoJUnitRunner.class)
public class WrapperUtilsTest {
@Mock Class class1;
@Mock Class class2;
@Mock Supplier<WrapperClass> wrapped_class_supplier;
@Test public void ensure_that____whatever() {
// given
BDDMockito.given(wrapped_class_supplier.get()).willReturn(new WrapperClass(class1, class2));
WrapperUtils tested_utils = new WrapperUtils(wrapped_class_supplier);
// when
tested_utils.processClass();
// then
verify(class1).someInteraction();
verify(class2).someInteraction();
}
}
I strongly advice you to follow Test Driven Development methodology it really helps to write good software. 我强烈建议您遵循“ 测试驱动开发”方法,这确实有助于编写出色的软件。 Also there's this book Growing Object Oriented Software Guided by Tests that is a great read, the book may seem old but it is still describes best practices. 此外,还有一本书, 《由测试指导的面向对象的成长软件 》( Growing Object Oriented Software by Tests)读得很好,这本书看似古老,但仍在描述最佳实践。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.