假设我们有一个接口有两种方法:
public interface MyInterface {
public SomeType first();
public SomeType second();
}
此界面由MyInterfaceImpl
实施。在实施过程中,first()
调用second()
来检索一些结果。
我想构建一个单元测试,根据first()
的内容来断言second()
的内容,类似于:
1 public class MyInterfaceTest {
2 private MyInterface impl = new MyInterfaceImpl();
4 @Test
5 public void testFirst() {
6 // modify behaviour of .second()
7 impl.first();
8 assertSomething(...);
10 // modify behaviour of .second()
11 impl.first();
12 assertSomethingElse(...);
13 }
14 }
是否有一种简单的方法可以在行2
上创建模拟,以便直接调用所有对所选方法的调用(例如first()
)(委托给MyInterfaceImpl
)其他方法(例如second()
)替换为模拟对应物?
对于静态方法,这实际上非常容易使用PowerMock,但我需要类似动态的方法。
基于
的解决方案MyInterface mock = EasyMock.createMock(MyInterface.class);
MyInterface real = new MyInterfaceImpl();
EasyMock.expect(mock.first()).andReturn(real.first()).anyTimes();
EasyMock.expect(mock.second()).andReturn(_somethingCustom_).anyTimes();
不够好,特别是对于有很多方法的接口(很多样板)。我需要转发行为,real
实际上取决于其他模拟。
我希望这样的东西可以由框架处理,而不是由我自己的类处理。这可以实现吗?
答案 0 :(得分:2)
如果first()
的实现必须调用second()
,那么您应该很可能为first()
和second()
设置单独的界面。然后,您可以拆分实现,并在测试second()
时模拟first()
。如果没有first()
和second()
的更具体的例子,肯定会说它很棘手。
在实现类上使用EasyMock来模拟只 second()
调用可能工作,但你好像不想这样做。这个可能要求告诉EasyMock将调用传递给first()
到正常实施 - 我不确定。
另一种选择可能是在测试类中实现子类化(作为嵌套类),允许您仅为了测试而覆盖second()
。它虽然很难看。
就我个人而言,我不想伪造一个班级的部分来测试其余部分。我更愿意假装所有一个类的依赖。
答案 1 :(得分:1)
可能你可以使用Dynamic Proxy。
答案 2 :(得分:1)
好老的子类化怎么样?我的意思是
private MyInterface impl = new MyInterfaceImpl(){
public final MyInterface mock = EasyMock.createMock(MyInterface.class);
@override //only the method you need to mock
public SomeType second(){
return mock.second();
}
}
@Test
public void testFirst() {
// modify behaviour of .second()
EasyMock.expect(impl.mock.second()).andReturn("What I want").anyTimes();
impl.first();
assertSomething(...);
// modify behaviour of .second()
EasyMock.expect(impl.mock.second()).andReturn("Now I want something else").anyTimes();
impl.first();
assertSomethingElse(...);
}
您没有测试要测试的确切类,而是测试匿名子类。但是我们可以假设子类在Java中工作正常。; - )