1

2 つのメソッドを持つインターフェースがあるとします。

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実際には他のモックに依存するため、転送動作が必要です。

このようなものは、自分のクラスではなく、フレームワークによって処理されることを期待しています。これは達成可能ですか?

4

3 に答える 3

2

It sounds like you should quite possibly have separate interfaces for first() and second(), if the implementation of first() has to call second(). You could then split the implementation too, and mock out second() while testing first(). Without a more concrete example of what first() and second() are, it's tricky to say for sure.

Using EasyMock on the implementation class to mock out only second() call might work, but you don't seem to want to do that anyway. This may require telling EasyMock to pass calls to first() through to the normal implementation - I'm not sure.

Another option might be to subclass the implementation within the test class (as a nested class) allowing you to override just second() for the purposes of testing. It's pretty ugly though.

Personally I don't like faking out part of a class just to test the rest. I'd much rather fake out all a class's dependencies.

于 2011-03-29T16:42:29.623 に答える
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 に答える
1

おそらく、 Dynamic Proxyを使用できます。

于 2011-03-29T16:53:35.397 に答える