web-dev-qa-db-ja.com

Mockito:呼び出されたときにvoidメソッドをスタブしてコードを実行する方法

リポジトリーを持つ別のクラス(Holderクラス)をテストするために、リポジトリー・クラスをスタブしたい。リポジトリインターフェースはCRUD操作をサポートし、多くのメソッドがありますが、Holderクラスの単体テストでは、それらの2つを呼び出すだけで済みます。リポジトリインターフェース:

public interface IRepo {
    public void remove(String... sarr);

    public void add(String... sarr);

    //Lots of other methods I don't need now
}

インスタンスを保存できるリポジトリモックを作成し、addremoveのみのロジックを定義し、addおよび削除します。

私が行った場合:

IRepo repoMock = mock(IRepo.class);

次に、各メソッドで何もしないダムオブジェクトがあります。これで問題ありません。追加と削除の動作を定義するだけです。

Set<String>とスタブは、セットで機能するこれらの2つのメソッドのみです。次に、IRepoを持つホルダーをインスタンス化し、部分的にスタブされたモックを挿入し、ホルダーを実行した後、セットをチェックして、セットに必要なものが含まれていることを確認します。

廃止されたメソッドremoveを使用して、stubVoidのようなvoidメソッドを部分的にスタブできました:

Set<String> mySet = new HashSet<>();
stubVoid(repoMock).toAnswer(new Answer<Void>() {

    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
        Object[] args = invocation.getArguments();
        String[] stringsToDelete = (String[]) args[0];
        mySet.removeAll(Arrays.asList(stringsToDelete));
        return null;
    }
}).on().remove(Matchers.<String>anyVararg());

しかし非推奨であり、IRepoの部分的な実装を作成するよりもはるかに優れています。もっと良い方法はありますか?

注:Java 7つだけ回答してください。これはAndroidで実行する必要があります。

14
Mister Smith

使用できます

  Mockito.doAnswer(new Answer<Void>() {
        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            //DO SOMETHING
            return null;
        }
    }).when(...).remove(Matchers.<String>anyVararg());

Javadocから:

汎用的なAnswerでvoidメソッドをスタブ化する場合は、doAnswer()を使用します。

コンパイラーは括弧内のvoidメソッドを好まないため、voidをスタブするにはMockito.when(Object)とは異なるアプローチが必要です...

例:

    doAnswer(new Answer() {
    public Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        Mock mock = invocation.getMock();
        return null;
    }}).when(mock).someMethod();

Mockitoのjavadocの例を参照してください

20
Jens

あなたが持っていると仮定します

public class IFace {
    public void yourMethod() {            
    }
}

それからあなたはそれをあざけるために

    IFace mock = Mockito.mock(IFace.class);
    Mockito.doAnswer(new Answer() {
        @Override
        public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
            //PUT YOUR CODE HERE
            return null;
        }
    }).when(mock).yourMethod();
3
talex

あなたが本当に嫌いならreturn nullAnswerの実装で、voidメソッドに委譲する独自のAnswer実装を作成できます。

public abstract class DoesSomethingAnswer implements Answer<Void> {

    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
        doSomething(invocation);
        return null;
    }

    protected abstract void doSomething(InvocationOnMock invocation);    
}

次に、テストの行が1行少なくなります。

    Set<String> mySet = new HashSet<>();
    Mockito.doAnswer(new DoesSomethingAnswer() {
        @Override
        protected void doSomething(InvocationOnMock invocation) {
            Object[] args = invocation.getArguments();
            String[] stringsToDelete = (String[]) args[0];
            mySet.removeAll(Arrays.asList(stringsToDelete));
        }
    }).when(repoMock).remove(Matchers.<String> anyVararg());

または、呼び出しからの引数だけが必要な場合:

public abstract class DoesSomethingAnswer implements Answer<Void> {

    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
        doSomething(invocation.getArguments());
        return null;
    }

    protected abstract void doSomething(Object[] args);
}
1
Ruben