1

私はmockito spyを使いたいです。

次の両方の方法で戻り値を設定すると:

when(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user)).thenReturn(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user, fakeNowDate));

doReturn(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user, fakeNowDate)).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);

戻り値が熱心に評価されていることがわかります

この「設定」行が実行されたときを意味します。

スパイにオンデマンドでのみ戻り値を評価させるにはどうすればよいですか?

「いつ」条件が満たされたときを意味します。

アップデート

@RobbyCornelissen のおかげで、私はこのコードを試しました:

    when(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user)).thenAnswer(new Answer() {
        public Object answer(InvocationOnMock invocation) {
            Object[] args = invocation.getArguments();
            ImagesSorter mock = (ImagesSorter)invocation.getMock();
            return mock.sortImages((List<Image>)args[0], (UserInfo)args[1], fakeNowDate);
        }
    });

しかし、それは役に立ちませんでした:

1) "when" 式がすぐに呼び出された。(要らない)

2) 最終的にコールバックは呼び出されませんでした。

4

2 に答える 2

2

最初に、部分的なモックについて警告させてください。これはコードが実際に行っていることであり、設計上間違っているからです。テスト対象の行動を構成するために戦略パターンを使用する方が適切かもしれません。Mockito チーム (私を含む) は、可能な限り部分モックを避けることを強くお勧めします。

編集:コードがわからず、テスト対象のコンポーネントが正確にはわかりませんが、収集したものから、画像の並べ替えを担当するタイプがあり、それを呼び出しましょうImagesSorter

  1. したがって、最初のケースImagesSorterはテスト対象の依存関係であるため、この場合はのモックをスタブするだけで済みImagesSorterます。

  2. ただし、それImagesSorter自体がテスト対象であり、このクラスの特別なメソッドをスタブ化することは部分モックと呼ばれ、明らかに間違っています。テストで製品コードの内部を公開します。したがって、いくつかの解決策があります。

    1. 回答に示されているコード スニペットが示すように、解決策の 1 つは、日付を提供することが唯一の責任であるfakeDateようなものを使用せずnew Date()、単純なクラスをコーディングすることです。TimeSourceそして、テストでは、これの本質はTimeSOurceオーバーライドされる可能性があります。

      より簡単な解決策は、この機能が組み込まれている JodaTime を使用することです。

    2. テストの範囲が日付の変更を超えている場合は、ImagesSorter他のオブジェクトで構成する方法が必要になる可能性があります。それを行う方法に関するインスピレーションは、guava のキャッシュ ビルダーで見つけることができます。構成が非常に単純な場合は、単純なコンストラクターでそれを行うことができます。

      それは次のようになります:

      class ImagesSorter { 
          ImagesSorterAlso algo;
          ImagesSorter(ImagesSorterAlgo algo) { this.algo = algo; }
          Iterable sortImages(...) {
             algo.sort(...);
          }
      }
      
      interface ImagesSorterAlgo {
          Iterable sort(...);
      }
      

あなたの質問について:

1) "when" 式がすぐに呼び出された。(要らない)

スパイであることが予想されるimagesSorterSpyため、デフォルトでは実際のコードを呼び出します。代わりに、@RobbyCornelissen が示したのと同じ代替 API を使用する必要があります。すなわち

doAnswer(sortWithFakeDate()).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);

// with BDD aliases (BDDMockito) which I personnaly finds better
willAnswer(sortWithFakeDate()).given(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);
will(sortWithFakeDate()).given(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);

sortWithFakeDate()答えを返す静的ファクトリメソッドになるため、コードは読みやすく、他の場所で再利用される可能性があります。

2) 最終的にコールバックは呼び出されませんでした。

この問題は、おそらく引数が等しくないことが原因です。方法を確認する必要があるかもしれませんequals。または、any()マッチャーを使用してスタブを緩和します。

于 2014-10-01T10:58:02.370 に答える
1

使用している引数とクラスのタイプがわからないため、完全な例を提供することはできませんが、Answer<T>インターフェイスでコールバックを使用してスタブできます。

Mockito.doAnswer(new Answer() {
    Object answer(InvocationOnMock invocation) {
         ImagesSorter mock = (ImagesSorter) invocation.getMock();
         Object[] args = invocation.getArguments();

         return mock.sortImages((List<Image>) args[0], (UserInfo) args[1],
                 fakeNowDate);
    }
}).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);
于 2014-10-01T10:10:02.453 に答える