我有以下要测试的类和方法:
public class MyClass{
private MyObject svc;
private MyObject2 svc2;
public MyClass(MyObject svc){
this.svc = svc;
this.svc2 = new MyObject2(svc);
}
public void getSvc(){
Result response = this.svc.getResponse();
if(!response.isEmpty())
this.svc2.filterResponse(response);
else
System.out.println("empty");
}
}
但是我正在努力成为无效方法。我该如何测试filterResponse仅在我的响应不为空时被调用?
答案 0 :(得分:2)
这是一个设计问题,因为被测对象对其执行设计功能的真正需求并不诚实。它通过new MyObject2(...)
紧密地耦合自身,从而使隔离测试变得困难(并非不可能)。
MyObject2
依赖于MyObject
的事实是MyClass
不需要了解的实现细节。
遵循显式依赖原理,
方法和类应明确要求(通常通过方法参数或构造函数参数)它们所需的任何协作对象,以使其正常运行。
MyClass
应该相应地重构
public class MyClass{
private MyObject svc;
private MyObject2 svc2;
public MyClass(MyObject svc, MyObject2 svc2){
this.svc = svc;
this.svc2 = svc2;
//this.svc2 = new MyObject2(svc); // <-- remove implementation details
}
public void getSvc(){
Result response = this.svc.getResponse();
if(!response.isEmpty())
this.svc2.filterResponse(response);
else
System.out.println("empty");
}
}
允许在进行单独测试时将必要的模拟/存根明确地注入到测试对象中。
//Arrange
MyObject svc = mock(MyObject.class);
MyObject2 svc2 = mock(MyObject2.class);
MyClass subject = new MyClass(svc, svc2);
Result response = mock(Result.class);
when(response.isEmpty()).thenReturn(false);
when(svc.getResponse()).thenReturn(response);
//Act
subject.getSvc();
//Assert
verify(svc2, times(1)).filterResponse(response); //verify method call inside void method
被测方法为void
的事实与验证行为无关。
答案 1 :(得分:0)
如果打算使用这种设计,并且您不能修改现有代码。您可以采用以下方法:
答案 2 :(得分:0)
您应该对myClass进行自动装配或注入模拟,因为它应该创建一个bean,以便在调用getSvc()时应该满足您的条件