モッキート。メソッドの引数を確認する


220

私はこれについてグーグルで調べましたが、関連するものは何も見つかりませんでした。私はこのようなものを持っています:

Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj )).thenReturn(null);

Testeable testableObj = new Testeable();
testableObj.setMockeable(mock);
command.runtestmethod();

ここで、mymethod(Object o)runtestmethod()で呼び出されたが、o他ではなくObject で呼び出されたことを確認します。しかし、私は、たとえば、次のように、検証に置いたものは何でも、常にテストに合格します。

Mockito.verify(mock.mymethod(Mockito.eq(obj)));

または

Mockito.verify(mock.mymethod(Mockito.eq(null)));

または

Mockito.verify(mock.mymethod(Mockito.eq("something_else")));

私はいつもテストに合格します。どうすればその検証を実行できますか(可能な場合)?

ありがとうございました。

回答:


334

の代替ArgumentMatcherArgumentCaptorです。

公式の例:

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

キャプターは、@ Captorアノテーションを使用して定義することもできます。

@Captor ArgumentCaptor<Person> captor;
//... MockitoAnnotations.initMocks(this);
@Test public void test() {
    //...
    verify(mock).doSomething(captor.capture());
    assertEquals("John", captor.getValue().getName());
}

1
サンプルをありがとう!使用したことはありません。コードにキャプターのようなものがあると少し変に感じますが、それは助けになりました。
アルテミス2016年

1
ハハ、私は質問を理解しませんでした、しかし答えは私を大いに助けました。おかげで:-)
マーカスK.

13
重要:モックを使用したは、verify()/ capture()を呼び出します。以前に「インストール」する必要があると思っていました...
Daniel Alder

1
この回答をありがとう!
Jose Flavio QuispeIrrazábal19年

これは素晴らしい答えです!! どうもありがとうございました!
ウルキーイゴール

61

オブジェクトの.equalsメソッドを使用して論理的等価を実行しようとしていますか?Mockitoに含まれているargThatマッチャーを利用してこれを行うことができます

import static org.mockito.Matchers.argThat

次に、各オブジェクトの.equalsメソッドを遅延させる独自の引数マッチャーを実装できます

private class ObjectEqualityArgumentMatcher<T> extends ArgumentMatcher<T> {
    T thisObject;

    public ObjectEqualityArgumentMatcher(T thisObject) {
        this.thisObject = thisObject;
    }

    @Override
    public boolean matches(Object argument) {
        return thisObject.equals(argument);
    }
}

コードを使用して、コードを更新して読み取ることができます...

Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj)).thenReturn(null);

Testeable obj = new Testeable();
obj.setMockeable(mock);
command.runtestmethod();

verify(mock).mymethod(argThat(new ObjectEqualityArgumentMatcher<Object>(obj)));

完全な等価性(メモリ内の同じオブジェクト)を取得する場合は、次のようにします。

verify(mock).mymethod(obj);

これにより、一度呼び出されたことを確認します。


1
そのために、ReflectionEqualsクラスのビルドを使用できます。
takacsot 2014

2
あなたの答えのために+1。しかし、それverify(mock).mymethod(obj);は正確な等価性(メモリ内の同じオブジェクト)をチェックしないことを追加したいと思います。代わりに、上書きされた可能性があるオブジェクトのequals-methodを使用します。
efux

の匿名実装を作成して、ArgumentMatcher冗長を減らすこともできます。
ボッチニアク2015

1
詳細:デフォルトでは、/ recordedオブジェクトの/ メソッドではなくverify()、/ inbound引数の/ equals()メソッドを呼び出しますequals()。テストサブジェクトが特定のオブジェクトインスタンスを返し、サブジェクトがそのインスタンスの透明なデコレータであると想定されるものを返すことを確認しようとしない限り、これは無関係です。verify引数のequals()デコレータを知ることはできません。一方、デコレータequals()はオリジナルを許容するように書き直されます。この場合、テストは誤って失敗します。
マークマッケンナ2016年

54
  • eq他のマッチャーを使用しない場合、マッチャーは必要ありません。
  • 正しい構文を使用していない-メソッドの呼び出しはの外で行う必要があり.verify(mock)ます。これで、何も検証せずに(メソッド呼び出しを行わずに)メソッド呼び出しの結果の検証を開始します。したがって、すべてのテストに合格しています。

コードは次のようになります。

Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");

私は以前に、そして今度は確かにそれを試しました。私はまだ同じ問題を抱えています、テストは常に合格します。
manolowar 2010

2
参照によって確認
cnexans '10 / 09/18

17

argThat プラスラムダ

これが引数の検証に失敗する方法です。

    verify(mock).mymethod(argThat(
      (x)->false
    ));

どこ

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;

argThat プラスアサート

上記のテストは「言う」でしょうExpected: lambda$... Was: YourClass.toSting...。ラムダでアサートを使用すると、より具体的な失敗の原因を取得できます。

    verify(mock).mymethod(argThat( x -> {
      assertThat(x).isNotNull();
      assertThat(x.description).contains("KEY");
      return true;
    }));

ただし、これは1つのメソッド呼び出しでのみ機能します。検証されたメソッドが2回以上呼び出された場合、mockitoは呼び出されたすべての組み合わせを各検証者に渡します。そのため、mockitoは、検証者trueが引数セットの1つに対してサイレントに戻りfalse、他の有効な呼び出しに対して(アサート例外なし)であることを期待します。その期待は、1つのメソッド呼び出しでは問題ではありません。1回だけtrueを返す必要があります。

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;

今テストは言う:Expected: Obj.description to contain 'KEY'. Was: 'Actual description'。注:assertJアサーションを使用しましたが、どのアサーションフレームワークを使用するかはあなた次第です。


argThat 複数の引数を持ちます。

を使用する場合argThatすべての引数に一致を指定する必要があります。例えば:

    verify(mock).mymethod(eq("VALUE_1"), argThat((x)->false));
    // above is correct as eq() is also an argument matcher.

verify(mock).mymethod("VALUE_1", argThat((x)->false));

// above is incorrect; an exceptoin will be thrown, as the fist arg. is given without an argument matcher.

どこ:

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;

eq マッチャー

引数が等しいかどうかを確認する最も簡単な方法:

verify(mock).mymethod(eq(expectedValue));
// NOTE:   ^ where the parentheses must be closed.

直接の議論

参照による比較が許容できる場合は、次に進みます。

verify(mock).mymethod(expectedArg);
// NOTE:   ^ where the parentheses must be closed.

元の質問の失敗の根本原因は、括弧の間違った場所でした:verify(mock.mymethod...。それは間違っていました。権利は:verify(mock).*


1
これは私のお気に入りの答えであり、機能し、他よりもはるかにエレガントです。
Airwavezx

11

この方法でMockito.verifyを使用しました

@UnitTest
public class JUnitServiceTest
{
    @Mock
    private MyCustomService myCustomService;


    @Test
    public void testVerifyMethod()
    {
       Mockito.verify(myCustomService, Mockito.never()).mymethod(parameters); // method will never call (an alternative can be pick to use times(0))
       Mockito.verify(myCustomService, Mockito.times(2)).mymethod(parameters); // method will call for 2 times
       Mockito.verify(myCustomService, Mockito.atLeastOnce()).mymethod(parameters); // method will call atleast 1 time
       Mockito.verify(myCustomService, Mockito.atLeast(2)).mymethod(parameters); // method will call atleast 2 times
       Mockito.verify(myCustomService, Mockito.atMost(3)).mymethod(parameters); // method will call at most 3 times
       Mockito.verify(myCustomService, Mockito.only()).mymethod(parameters); //   no other method called except this
    }
}

5

モック可能クラスのequalsメソッドを確認しましたか?これが常にtrueを返す場合、または同じインスタンスを同じインスタンスに対してテストし、equalメソッドが上書きされない場合(したがって、参照に対してのみチェックされる場合)は、trueを返します。


4

もう1つの方法は、1つを再定義する代わりにorg.mockito.internal.matchers.Equals.Equalsメソッドを使用することです。

verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted)));

3

same()マッチャーで試しましたか?のように:

verify(mockObj).someMethod(same(specificInstance));

同じ問題がありました。eq()マッチャーとrefEq()マッチャーで試してみましたが、常に誤検知がありました。same()マッチャーを使用すると、引数が異なるインスタンスである場合にテストが失敗し、引数が同じインスタンスである場合はパスしました。


-1

TypeSafeDiagnosingMatcherを使用することもできます

    private Matcher<GetPackagesRequest> expectedPackageRequest(final AvailabilityRequest request) {
    return new TypeSafeDiagnosingMatcher<GetPackagesRequest>() {

        StringBuilder text = new StringBuilder(500);

        @Override
        protected boolean matchesSafely(GetPackagesRequest req, Description desc) {
            String productCode = req.getPackageIds().iterator().next().getValue();
            if (productCode.equals(request.getSupplierProductCode())) {
                text.append("ProductCode not equal! " + productCode + " , " + request.getSupplierProductCode());
                return true;
            }

            text.append(req.toString());
            return false;
        }

        @Override
        public void describeTo(Description d) {
            d.appendText(text.toString());
        }
    };
}

次に、その呼び出しを確認します。

Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request)));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.