1

假设我们有一个接口,它有两个方法:

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()MyInterfaceImplsecond()

对于静态方法,这实际上很容易使用 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实际上取决于其他模拟。

我希望这样的事情由框架处理,而不是由我自己的班级处理。这是可以实现的吗?

4

3 回答 3

2

听起来您很可能应该为first()and提供单独的接口second(),如果first()必须调用second(). 然后,您也可以拆分实现,并second()在测试时进行模拟first()first()如果没有关于什么和是什么的更具体的例子,second()很难确定。

在实现类上使用 EasyMock 来模拟 second()调用可能有效,但您似乎不想这样做。这可能需要告诉 EasyMock 将调用传递first()给正常的实现——我不确定。

另一种选择可能是将测试类中的实现子类化(作为嵌套类),允许您仅second()出于测试目的而覆盖。虽然它很丑。

就个人而言,我不喜欢为了测试其余部分而伪造课程的一部分。我宁愿伪造一个类的所有依赖项。

于 2011-03-29T16:42:29.623 回答
1

可能您可以使用Dynamic Proxy

于 2011-03-29T16:53:35.397 回答
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 中可以正常工作。;-)

于 2011-03-29T17:43:31.260 回答