50

EasyMockでいくつかのインターフェースを実装するモックオブジェクトを作成することは可能ですか?

たとえば、インターフェイスFooとインターフェイスCloseable

Rhino Mocksでは、モックオブジェクトを作成するときに複数のインターフェイスを提供できますが、EasyMockのcreateMock()メソッドは1つのタイプしか取りません。

Fooとの両方を拡張する一時的なインターフェースを作成し、それをモックするというフォールバックに頼ることなく、EasyMockでこれを達成することは可能Closeableですか?

4

6 に答える 6

83

私はNickHoltの答えに基本的に同意しますが、 mockitoは次の呼び出しであなたが求めることを実行できることを指摘する必要があると思いました。

Foo mock = Mockito.mock(Foo.class, withSettings().extraInterfaces(Bar.class));

明らかに、キャストを使用(Bar)mockする必要があります。モックをとして使用する必要があるBarが、そのキャストはスローされない場合ClassCastException

これは、まったくばかげているとはいえ、もう少し完全な例です。

import static org.junit.Assert.fail;
import org.junit.Test;
import static org.mockito.Mockito.*;
import org.mockito.Mockito;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import org.hamcrest.Matchers;

import java.util.Iterator;


public class NonsensicalTest {


    @Test
    public void testRunnableIterator() {
        // This test passes.

        final Runnable runnable = 
                    mock(Runnable.class, withSettings().extraInterfaces(Iterator.class));
        final Iterator iterator = (Iterator) runnable;
        when(iterator.next()).thenReturn("a", 2);
        doThrow(new IllegalStateException()).when(runnable).run();

        assertThat(iterator.next(), is(Matchers.<Object>equalTo("a")));

        try {
            runnable.run();
            fail();
        }
        catch (IllegalStateException e) {
        }
    }
于 2009-08-13T08:14:18.117 に答える
14

次のようなことを検討しましたか?

interface Bar extends Foo, Closeable {
}

次に、インターフェイスバーをモックしますか?

于 2009-07-23T09:58:30.817 に答える
10

EasyMockはこれをサポートしていないため、一時的なインターフェイスのフォールバックで立ち往生しています。

余談ですが、私は少しコードの匂いがします-メソッドは実際にオブジェクトを2つの異なるもの、この場合はFooCloseableインターフェイスとして扱う必要がありますか?

これは、メソッドが複数の操作を実行していることを意味し、それらの操作の1つが「閉じる」ことであるCloseableと思われますが、呼び出し元のコードが「閉じる」が必要かどうかを判断する方が理にかなっていますか?

このようにコードを構造化すると、「open」と「close」が同じtry ... finallyブロックに保持され、IMHOは、メソッドをより一般的にすることは言うまでもなく、コードを読みやすくし、を実装するだけのオブジェクトを渡すことができますFoo

于 2009-07-23T10:41:51.197 に答える
7

最も投票された回答の代替案は、まだMockitoに基づいていますが、注釈が付いています。次のように、注釈extraInterfacesから直接設定できます。Mock

@RunWith(MockitoJUnitRunner.class)
public class MyTest {
    @Mock(extraInterfaces = Closeable.class)
    private Foo foo;
    ...
}

注意: extraInterfacesタイプClass<?>[]なので、必要に応じて複数のインターフェースを指定できます。

追加のインターフェースのメソッド呼び出しをモックする必要がある場合は、モックをキャストする必要があります。たとえば、モックIOExceptionを呼び出すときにをスローしたい場合、対応するコードは次のようになります。close()foo

Mockito.doThrow(IOException.class).when((Closeable) foo).close();
于 2018-04-18T18:23:39.637 に答える
2

私の知る限り、複数のインターフェースのモックを明示的にサポートしているJava用のモックツールはJMockitだけです。(この機能を追加するための私のインスピレーションは、.NETツールであるMoqとRhino Mocksから来ました。)

例(mockit.ExpectationsUsingMockedTestJUnit 4テストクラスから):


@Test
public <M extends Dependency & Runnable> void mockParameterWithTwoInterfaces(final M mock)
{
   new Expectations()
   {
      {
         mock.doSomething(true); returns("");
         mock.run();
      }
   };

   assertEquals("", mock.doSomething(true));
   mock.run();
}

DependencyおよびRunnableはインターフェースです。doSomethingメソッドは最初のものと2番目のものに属しrunます。

于 2009-07-26T17:57:08.050 に答える
2

この問題を解決する別の方法は、CGLibミックスインを使用することです。

final Interface1 interface1 = mockery.mock(Interface1.class);
final Interface2 interface2 = mockery.mock(Interface2.class);

service.setDependence(Mixin.create(new Object[]{ interface1, interface2 }));

mockery.checking(new Expectations(){{
    oneOf(interface1).doSomething();
    oneOf(interface2).doNothing();
}});

service.execute();

これが良い考えであるかどうかにかかわらず、それは議論次第です...

于 2014-01-10T15:50:25.100 に答える