mockitoマニュアル

Mockitoの入門編等は/tag/mockitoを参照して欲しい。以下のマニュアルは翻訳途中であり、なおかつ初心者向けではない

2018/6/21 現時点の最新バージョン2.19.0の訳に変更することにした。

以下はhttp://static.javadoc.io/org.mockito/mockito-core/2.19.0/org/mockito/Mockito.htmlの訳(Version 2.19.0、現在翻訳進行中)

Mockitoライブラリは、モックの生成、検証、スタビングを行うものである。

このJavaDocの内容は、http://mockito.orgでも提供されている。すべてのドキュメントはJavaDocの形で保持されている。そうすれば、ウェブサイトにあるものとソースコードが一貫性を保てるからだ。オフライン作業中でもIDEからドキュメントにアクセスできることになる。それが動機づけになるのだ、Mockitoのデベロッパがドキュメントを最新にしようとする。彼らが毎日書き、コミットするすべてのコードについてである。

Contents

0. Mokito2へのマイグレーション

Mockitoの改良を継続するため、そして、さらなるユニットテストの体験を改良するため、皆さんにはMockito2.1.0にアップグレードしてほしい(現在は2.19.0)。Mockitoはセマンティック・バージョニングに従っており、互換性の無い変更はメジャーバージョンのアップグレードに限られる。

ライブラリのライフサイクルとして、全く新しい機能の導入において非互換の変更が必要なのだ。これには、既存のふるまいや、あるいはAPIの変更され含まれる。非互換の変更を含む、新たなリリースの包括的ガイドとしては、What’s new in Mockito 2を見てほしい。Mockito 2を楽しんでもらいたい。

0.1. MockitoのAndroidサポート

Mockito 2.6.1において、我々は「ネイティブ」なAndroidサポートを公開した。Androidのサポートをするには「mockito-android」ライブラリをプロジェクトに追加して欲しい。このアーティファクトは、同じMockito組織であり、Androidに次にようにインポートできる。

 repositories {
   jcenter()
 }
 dependencies {
   testCompile "org.mockito:mockito-core:+"
   androidTestCompile "org.mockito:mockito-android:+"
 }

同じユニットテストを普通のVM上で継続できるだろう、’mockito-core’アーティファクトを使うことによってだ。上に示したように、’testCompile’スコープにいれてほしい。

注意が必要なのは、Androidではinline mock makerが使えないことだ。これはAndroidのVMの制限による。もし、Android上でのモック作成に問題があるようであれば、the official issue trackerにて報告してほしい。Androidバージョンを添えてだ。

0.2. コンフィギュレーション無しのinline mock making

2.7.6以降、’mockito-inline’アーティファクトを提供している。これでinline mocki makingを行うことができる、MockMaker拡張ファイル無しでだ。これを使うには、’mockito-core’アーティファクトの代わりに’mockit-inline’を使ってほしい。

 repositories {
   jcenter()
 }
 dependencies {
   testCompile "org.mockito:mockito-inline:+"
 }

このアーティファクト廃止されるかもしれないことに注意。
もしinline mock making 機能がデフォルトのMock Makerに取り込まれればそうなる。

inline mock makingについては39.を見てほしい。

1.ふるまいを検証してみよう

以下の例は、Listをモックするものだ。このインターフェースには多くの人になじみがあるだろう(add(), get(), clear()メソッドなど)。

実際には、Listをモックしないようにしてほしい.
本物のインスタンスを使ってほしい。

 //Mockitoをstatic importすると、コードがきれいに書ける
 import static org.mockito.Mockito.*;

 //モックを作る
 List mockedList = mock(List.class);

 //モックオブジェクトを使ってみる
 mockedList.add("one");
 mockedList.clear();

 //検証する
 verify(mockedList).add("one");
 verify(mockedList).clear();

いったん作成されると、モックはすべての作用を記録している。後で興味のある作用についてだけ検証することができる。

2. スタビングとは?

 //コンクリートクラスのモックを作成することができる、インターフェースだけではなく
 LinkedList mockedList = mock(LinkedList.class);

 //スタブ化
 when(mockedList.get(0)).thenReturn("first");
 when(mockedList.get(1)).thenThrow(new RuntimeException());

 //以下は"first"を表示する
 System.out.println(mockedList.get(0));

 //以下は実行時例外を投げる
 System.out.println(mockedList.get(1));

 //以下は"null"を表示する、get(999)はスタブされていないから。
 System.out.println(mockedList.get(999));

 //スタブを検証することもできるけれども、冗長だろう。
  //If your code cares what get(0) returns then something else breaks (often before even verify() gets executed).
  //If your code doesn't care what get(0) returns then it should not be stubbed. Not convinced? See here.
  verify(mockedList).get(0);
  • デフォルトでは、すべての返り値のあるメソッドについては、モックはnull, 空のコレクション、適当なプリミティブやプリミティブラッパ値(例えば、0, false, …)などを返す。
  • スタブ化はオーバライドできる。例えば、共通のスタブ化をfixtureセットアップで行い、テストメソッド中でオーバライドする。ただ、スタブ化のオーバライドは「スタブしすぎ」の可能性もある。
  • 一度スタブ化されると、何度呼び出されようが、同じ値を返す。
  • 最後のスタブ化が重要だ。同じメソッドを同じ引数で何度もスタブ化した場合だ。言い換えれば、スタブ化の順序が重要だ。しかし、これが意味を持つのは稀である。つまり、正確に同じメソッド呼び出しのときや、あるいときには、引数マッチャーが使われたときなどだ。

3.引数の一致

Mockitoは引数が一致するかどうかを通常のJavaスタイルでチェックする。つまり、equals()メソッドを使う。しかし、もっとフレキシブルな方法が必要になることもある。その場合は引数マッチャーを使うことができる。

 //ビルトインのanyInt()引数マッチャーを使ってスタブ化
 when(mockedList.get(anyInt())).thenReturn("element");

 //カスタムマッチャー(例えば、自身の実装を返すメソッドisValid())を使ってスタブ化
 when(mockedList.contains(argThat(isValid()))).thenReturn("element");

 //以下は"element"を表示する
 System.out.println(mockedList.get(999));

 //引数マッチャーを使って検証を行うこともできる
 verify(mockedList).get(anyInt());

 //引数マッチャーはJava8のラムダを使っても書ける
 verify(mockedList).add(argThat(someString -> someString.length() > 5));

引数matcherによってフレキシブルな検証とスタブ化をすることができる。
ここここを見てほしい、ビルトインマッチャーとカスタムマッチャー/hamcrestマッチャーについて。

カスタム引数マッチャーについては、ArgumentMatcherクラスのJavaDocを見てほしい。

複雑な引数マッチングについて妥当性を保つこと。
たまにanyX()マッチャーを使う程度の、equals()を使用した自然なマッチスタイルは、クリーンでシンプルなテストになる。

equals()によるマッチングができるようにコードをリファクタリングしたり、あるいはequals()を実装した方が良い場合もある。

また、セクション15あるいはArgumentCaptorを読むこと。ArgumentCaptorは後のアサーションのために、引数値をキャプチャする特別な引数matcherである。

引数matcherに関する注意

引数matcherを使う場合は、すべての引数がmatcherで提供されなければならない。

   verify(mock).someMethod(anyInt(), anyString(), eq("third argument"));
   //上は正しい。eq()も引数matcherである

   verify(mock).someMethod(anyInt(), anyString(), "third argument");
   //上は不正。なぜなら、三番目の引数は引数matcherとして提供されていない。

anyObject()やeq()といったメソッドはマッチャーを返さない。内部的には、それらはスタック上のマッチャーを記録し、ダミーの返り値を返すだけである(通常はnull)。この実装は、Javaコンパイラに強制されるstatic型安全性のゆえである。その結果、anyObject()やeq()メソッドは、検証/スタブ化メソッドの外で使うことはできない。

4. 正確な呼び出し数を検証する。at least x / never

 //モックを使う
 mockedList.add("once");

 mockedList.add("twice");
 mockedList.add("twice");

 mockedList.add("three times");
 mockedList.add("three times");
 mockedList.add("three times");

 //次の二つの検証は全く同じ。デフォルトでは、times(1)が適用される。
 verify(mockedList).add("once");
 verify(mockedList, times(1)).add("once");

 //正確な呼び出し数を検証する。
 verify(mockedList, times(2)).add("twice");
 verify(mockedList, times(3)).add("three times");

 //never()を使う。never()はtimes(0)の別名である。
 verify(mockedList, never()).add("never happened");

 //atLeast()/atMost()を使った検証
 verify(mockedList, atLeastOnce()).add("three times");
 verify(mockedList, atLeast(2)).add("five times");
 verify(mockedList, atMost(5)).add("three times");

times(1)はデフォルトなので、これを省略することができる。

5. voidメソッドの例外スタブ化

   doThrow(new RuntimeException()).when(mockedList).clear();

   //以下はRuntimeExceptionを投げる
   mockedList.clear();

12.のdoThrow|doAnswerファミリーを参照のこと。

6. 順序の検証


// A. メソッドが特定順序で呼び出されるべき単一のモック List singleMock = mock(List.class); //単一モックを使用する singleMock.add("was added first"); singleMock.add("was added second"); //単一モックに対するinOrderベリファイアを作成する InOrder inOrder = inOrder(singleMock); //"was added first"、"was added second"の順序であることを検証 inOrder.verify(singleMock).add("was added first"); inOrder.verify(singleMock).add("was added second"); // B. 特定順序で使用されるべき複数のモック List firstMock = mock(List.class); List secondMock = mock(List.class); //モックを使う firstMock.add("was called first"); secondMock.add("was called second"); //inOrderオブジェクトを作成するが、順序検証に必要なすべてのモックを指定する InOrder inOrder = inOrder(firstMock, secondMock); //firstMock、secondMockの順序で呼び出されたことを検証 inOrder.verify(firstMock).add("was called first"); inOrder.verify(secondMock).add("was called second"); // AとBを混ぜて使うこともできる。

順序検証はフレキシブルに作られている。すべての作用(メソッド呼び出し)を一つ一つ検証する必要はなく、必要なものだけを検証すればよい。

また、InOrderオブジェクトには、順序検証に関連するオブジェクトだけを与えればよい。

7. モックのメソッド呼び出しが無かったことを確認する

 //モックを使う。mockOneのみが呼び出される。
 mockOne.add("one");

 //通常の検証
 verify(mockOne).add("one");

 //次の作用は一度も無かったことを検証
 verify(mockOne, never()).add("two");

 //他のモックは何の作用も無いことを検証
 verifyZeroInteractions(mockTwo, mockThree);

8. 冗長な呼び出しを見つける

 //モックを使う
 mockedList.add("one");
 mockedList.add("two");

 verify(mockedList).add("one");

 //次の検証は失敗 
 verifyNoMoreInteractions(mockedList);

注意:クラシックなexpect-run-verifyスタイルのモッキングを使っていたユーザは、すべてのテストメソッドでよくverifyNoMoreInteractions()を使いたがる。
しかし、verifyNoMoreInteractions()をすべてのテストメソッドで使うことは推奨されない。

verifyNoMoreInteractions()は手軽な宣言であるが、関係するときだけに使うこと。乱用することは、オーバースペックになりがちであり、メンテ性の低いテストコードになる。こちらを参照のこと。

never()を参照のこと。こちらの方が明快だし意図がはっきりする。

9. モック生成のショートカット – @Mockアノテーション

  • モック生成コードの繰り返しを避けることができる。
  • テストクラスが読みやすくなる。
  • 検証エラーが読みやすくなる。なぜなら、フィールド名によってモックを識別できるからだ。
   public class ArticleManagerTest { 

       @Mock private ArticleCalculator calculator;
       @Mock private ArticleDatabase database;
       @Mock private UserProvider userProvider;

       private ArticleManager manager;

重要:以下がベースクラスか、あるいはテストランナーに必要である。

 MockitoAnnotations.initMocks(testClass);

ビルトインランナーであるMockitoJUnitRunnerの使用を考慮すること。あるいは、MockitoRuleである。

MockitoAnnotationsを参照のこと。

10. 連続呼び出しのスタブ化(イテレータスタイルスタブ)

同じメソッド呼び出しに対し、異なる値を返したり異なる例外を投げたりしたい場合がある。

その典型がイテレータのモッキングである。Mockitoのオリジナルバージョンはこのような機能を持っていなかった。

例えば、Iteratorの代わりにIterableや単純なCollectionを使いたいことがある。これらは自然なスタブ化を提供する(つまり、本物のコレクションを使うわけだ)。

しかし、稀だが連続呼び出しをスタブ化できた方が便利なこともある。

 when(mock.someMethod("some arg"))
   .thenThrow(new RuntimeException())
   .thenReturn("foo");

 //一度目の呼び出し。RuntimeExceptionを投げる
 mock.someMethod("some arg");

 //二度目の呼び出し。"foo"を表示
 System.out.println(mock.someMethod("some arg"));

 //引き続いての呼び出し。やはり"foo"を表示(最後のスタブ化が有効) 
 System.out.println(mock.someMethod("some arg"));

以下のようにも書ける。連続スタブ化の短いバージョンである。

 when(mock.someMethod("some arg"))
   .thenReturn("one", "two", "three");

注意:.thenReturn()を連続させるのではなく、同じマッチャーや引数による複数のスタブ化を行うと、それぞれのスタブ化は前のものを上書きしてしまう。

 //mock.someMethod("some arg")を呼び出すと常に"two"を返す。
 when(mock.someMethod("some arg"))
   .thenReturn("one")
 when(mock.someMethod("some arg"))
   .thenReturn("two")

11. コールバックのスタブ化

Answerインターフェースを使ってのスタブ化を行うことができる。

これは、もともとのMockitoには無かった物議をかもすような機能である。我々はthenReturn(), thenThrow()を使ったシンプルなスタブ化を推奨する。これらはクリーンでシンプルなコードをテストするのに十分である。

しかし、一般的なAnswerインターフェースを必要とするならば、以下がその例である。

 when(mock.someMethod(anyString())).thenAnswer(new Answer() {
     Object answer(InvocationOnMock invocation) {
         Object[] args = invocation.getArguments();
         Object mock = invocation.getMock();
         return "called with arguments: " + args;
     }
 });

 //以下は"called with arguments: foo"を表示する。
 System.out.println(mock.someMethod("foo"));

12. voidメソッドのスタブ化のためのdoThrow()|doAnswer()|doNothing()|doReturn()ファミリー

voidメソッドをスタブ化するにはwhen(Object)とは異なるアプローチが必要である。なぜなら、コンパイラがカッコの中にあるvoidメソッドを嫌がるからだ。

voidメソッドに例外を投げさせたいときにdoThrow()を使う。

   doThrow(new RuntimeException()).when(mockedList).clear();

   //以下はRuntimeExceptionを投げる
   mockedList.clear();

doThrow(), doAnswer(), doNothing(), doReturn() and doCallRealMethod()は、いかなるメソッドの該当するwhen()の場所にも使用することができる。これが必要となるのは、以下のケースだ。

  • voidメソッドのスタブ化
  • spyオブジェクトのスタブ化(後述)
  • 同じメソッドの複数回のスタブ化。テストの途中でモックのふるまいを変更するため。

しかし、これらのメソッドをすべての場所でwhen()の代わりに使用しても良い。

これらについては以下を参照のこと。

13. リアルオブジェクトをスパイする

リアルオブジェクトに対するスパイを作成することができる。
(そのメソッドがスタブ化されていない限り)スパイのメソッドを呼び出すとリアルオブジェクトのメソッドが呼び出される。

リアルスパイは注意して時々使うようにしたい。例えば、レガシーコードを扱うような場合である。

リアルオブジェクトのスパイは「部分モッキング」に関係している。リリース1.8以前では、Mockitoスパイは部分モックではなかった。部分モックはcode smell(※)であると我々は考えるからである。

※訳注:まずいコードという意味らしい。ファウラーの「リファクタリング」が初出との説あり。

ある時点で、我々は部分モックの適当なユースケースを発見した(サードパーティ製インターフェース、レガシーコードの一時的なリファクタリングである。全文はここ

   List list = new LinkedList();
   List spy = spy(list);

   //お好みでメソッドをスタブ化する。
   when(spy.size()).thenReturn(100);

   //スパイを使うとリアルメソッド呼び出しになる。
   spy.add("one");
   spy.add("two");

   //"one"を表示する - リスト中の最初n要素である。
   System.out.println(spy.get(0));

   //size()メソッドはスタブ化されている - 100が表示される。
   System.out.println(spy.size());

   //お好みで検証する。
   verify(spy).add("one");
   verify(spy).add("two");

リアルオブジェクトをスパイする際の注意事項

  • スパイをスタブ化するためのwhen(Object)が使えない場合がある。したがって、スパイを使うバイはメソッドスタブ化にdoReturn|Answer|Throwの使用を考慮して欲しい。
   List list = new LinkedList();
   List spy = spy(list);

   //不可能、リアルメソッドが呼び出されてしまうため、IndexOutOfBoundsExceptionが発生する
   when(spy.get(0)).thenReturn("foo");

   //doReturnを使わざるをえない
   doReturn("foo").when(spy).get(0);

  • Mockitoは与えられたリアルインスタンスに呼び出しを移譲することはしない。そうではなく、実際にそのコピーを作成する。だから、もしリアルインスタンスの参照を保持し、そのメソッドを呼び出した場合、スパイがその呼び出しをわかっていると期待しないこと。必然的にスパイに対して、スタブ化されていないメソッドを呼び出すと、それはリアルインスタンスには何の影響も与えない。

  • finalメソッドに注意。 Mokcitoはfinalメソッドをモックできない。要するに、リアルオブジェクトをスパイし、finalメソッドをスタブ化しようとするとトラブルになる。また、これらのメソッドを検証することもできない。

14. スタブ化されていない呼び出しのデフォルト返り値を変更する (1.7より) ==

返り値について特殊な戦略を行うモックを作成することができる。
これは特に上級者向けであり、通常のテストでは必要ない。
しかし、レガシーシステムを扱う際には便利であろう。

メソッド呼び出しをスタブしない場合にのみ利用すべき、デフォルトのAnswerである。

   Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);
   Foo mockTwo = mock(Foo.class, new YourOwnAnswer()); 
 ```


[RETURNS_SMART_NULLS](http://static.javadoc.io/org.mockito/mockito-core/2.19.0/org/mockito/Mockito.html#RETURNS_SMART_NULLS)を参照のこと。

## 15. 後のアサーションのために引数をキャプチャする (1.8.0より)

Mockitoは自然なJavaスタイルで引数の検証を行う、つまりequals()メソッドを用いる。
これは引数マッチを行う場合の推奨される方法でもある。テストがクリーンでシンプルになるからだ。

しかし、ある引数について、実際の検証の後でアサーションを行った方が便利な場合がある。例えば、
```java
   ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
   verify(mock).doSomething(argument.capture());
   assertEquals("John", argument.getValue().getName());

注意:ArgumentCaptorは検証(verification)と共に利用することが推奨されるが、しかしスタブ化とともに使わない方がよい。
スタブ化とともに使うとリーダビリティを損なう、なぜなら、Captorはassert(verify あるいは ‘then’)ブロックの外で作成されるからだ.

また、これは欠陥の局所化も減少させてしまう。なぜなら、スタブ化メソッドが呼び出されなければ、何の引数もキャプチャされないからだ。

ある意味では、ArgumentCaptorはカスタム引数マッチャーに関連している(ArgumentMatcherのJavaDocを参照してほしい)。二つのテクニックは、特定の引数がどこでモックに渡されるかを確実にするために用いられる。

  • カスタム引数マッチャーは、再使用されることはあまりない
  • これが必要なのは、単純に引数値のassertを行うためである、完全な検証のための。

ArgumentMatcherを通してのカスタム引数マッチャーは、通常スタブ化以前の方がベターである。

16. リアル部分モック (1.8.0より)

メーリングリスト上での多くの議論とディスカッションの後に、Mockitoに部分モックサポートが追加された。以前には、我々は部分モックをコードスメル(悪いコードの予感)とみなしていたのだが、しかし、部分モックの正当なユースケースを発見した。ここを読んで欲しい。

1.8以前には、spy()はリアルな部分モックを作ってはおらず、ユーザの中には混乱する者もいた。spyについては13.か、あるいはspy()のJavaDocを読んでほしい。


//spy()メソッドによって部分モックを作成できる。 List list = spy(new LinkedList()); //選択的に部分モック機能を有効化することができる。 Foo mock = mock(Foo.class); // リアルな実装が「安全」であることを確認すること // もしリアル実装が例外を発生したり、特定の状態に依存するようであれば、トラブルになる。 when(mock.someMethod()).thenCallRealMethod();

いつものように、部分モックについては警告を読まねばならない:オブジェクト思考プログラミングというのは、おおよそ分離し、具体的な、SRPyなオブジェクトに複雑さを分割することによって、その複雑さと取り組むものである。このパラダイムに部分モックがどう合致するのだろうか?そうだね、合致しないね。部分モックの通常の意味としては、複雑さが、同じオブジェクトの異なるメソッドに移動したということだ。多くの場合、これは君がアプリをデザインする方法ではないと思う。

しかしながら、部分モックがハンディな方法となるレアケースもある:簡単には変更できないようなコードの場合だ(サードパーティインターフェース、レガシーコードの暫定的なリファクタリングなど)。しかし、私は部分モックは使わないね、新たな、テストドリブンの良くデザインされたコードではね。

17. モックのリセット (1.8.0より)

頭のいいMockitoユーザはこんな機能は使わないだろう、これは貧弱なテストの兆候だからだ。
通常はモックをリセットする必要などない、単にそれぞれのテストメソッドで新しいモックを作成すればよいのだ。

reset()の代わりに、どうかシンプルで小さく、フォーカスされたテストメソッドを書いてほしい。長ったらしく、スペックオーバーなテストではなく。最初のコードスメルの可能性が現れるのはテストメソッドの半ばだ。おそらくこれは、「テストしすぎ」ということだ。テストメソッドのわずかな声を見逃さないこと、「どうか私達を、小さく、単一のふるまいに集中させてください」という。これについてはmockitoのメーリングリストにいくつものスレッドがある。

我々がreset()を追加した理由は、コンテナーインジェクトモックを使えるようにするためである。ここを見てほしい。

自身を傷つけないこと。テストメソッドの半ばにあるreset()はコードスメルである。つまり、テストしすぎだ。

   List mock = mock(List.class);
   when(mock.size()).thenReturn(10);
   mock.add(1);

   reset(mock);
   // この時点でmockはインタラクションとスタブ化を忘れる。

18. トラブルシューティングと検証フレームワークの使用 (1.8.0より)

まず最初に、何かトラブルが起きたら、FAQを見てほしい。
http://code.google.com/p/mockito/wiki/FAQ

質問がある場合にもmockitoメーリングリストに投稿してほしい。
http://groups.google.com/group/mockito

次に、これを知ってほしい、mockitoは正しく使った時にのみ、検証を行うということだ。
しかし、落とし穴もある。validateMockitoUsage()のJavaDocを見てほしい。

19. ビヘイビア駆動開発のためのエイリアス (1.8.0より)

ビヘイビア駆動開発スタイル(BDD)でテストを書く場合には、//given //when //then というコメントを使う、これを、テストメソッドの基本パーツとするのだ。これこそ、我々がまさにテストで使っていることでわり、同じことを勧めるものだ。

Behavior Driven Development style of writing tests uses //given //when //then comments as fundamental parts of your test methods. This is exactly how we write our tests and we warmly encourage you to do so!

BDDについて学びたい場合は、これを見てほしい。
http://en.wikipedia.org/wiki/Behavior_Driven_Development

問題としては、現在の、標準的な役割を持つwhen語によるスタブ化APIは、//given //when //thenコメントとは、うまく統合しないことだ。

なぜなら、スタブ化は、テストのgivenコンポーネントに属しており、whenコンポーネントでは無いからだ。BDDMockitoクラスがエイリアスとして導入されたので、これを使ってスタブメソッドをBDDMockito.given(Object)メソッドを呼び出してほしい。これで、いまやナイスにBDDスタイルテストのgivenコンポーネントに統合できることになる。

以下のようになる。

 import static org.mockito.BDDMockito.*;

 Seller seller = mock(Seller.class);
 Shop shop = new Shop(seller);

 public void shouldBuyBread() throws Exception {
   //given
   given(seller.askForBread()).willReturn(new Bread());

   //when
   Goods goods = shop.buyBread();

   //then
   assertThat(goods, containBread());
 }

20. シリアライズ可能なモック (1.8.1より)

モックはシリアライズ可能にできる。この機能によって、Serializableであるような依存が要求されるところでモックを使うことができる。

警告:これはユニットテストでは滅多に使うべきではない。

この振る舞いは、特定のBDDスペックの特別なユースケースにおいて実装される。信頼できないような外部依存を持つようなものだ。これはウェブ開発に存在し、外部依存からやってきたオブジェクトが、レイヤーを通すためにシリアライズされる。

シリアライズ可能なモックを作るには、MockSettings.serializable()を使うこと。

   List serializableMock = mock(List.class, withSettings().serializable());

そのクラスが、すべての通常のシリアライズ要件が満たされている場合にモックはシリアライズ可能となる。

リアルオブジェクトのspyをシリアライズ可能にすることは、少々苦労する。というのは、spy()メソッドは、MockSettingsを受け入れるオーバーロードバージョンを持たないからだ。心配するな、こんなものは滅多に使わない。

 List list = new ArrayList();
 List spy = mock(ArrayList.class, withSettings()
                 .spiedInstance(list)
                 .defaultAnswer(CALLS_REAL_METHODS)
                 .serializable());

21. 新たなアノテーション: @Captor, @Spy, @InjectMocks (1.8.3より)

リリース1.8.3には新たなアノテーションがもたらされた。以下のケースで役に立つ。

  • @CaptorがArgumentCaptorの作成を簡単にする。 capture()の場所の引数が妙なジェネリッククラスのとき、コンパイラ警告を避けることができる。
  • @Spyはspy(Object)の代わりに使える。
  • @InjectMocksがテスト対象オブジェクトにモックやスパイを自動的に注入する。

@InjectMocksは@Spyアノテーションと共に使用することもできる。この意味としては、Mockitoがテスト下の部分モックにモックを注入するということである。この複雑さがもう一つの理由である、部分モックを避けるべきことの。部分モックについては、16.を見てほしい。

すべての新たなアノテーションは、MockitoAnnotations.initMocks(Object)で処理される。@Mockと同じようにだ。MockitoJUnitRunner かMockitoRuleを使うことができる。

22. タイムアウトによる検証 (1.8.5より)

タイムアウトによって検証する機能だ。これは、望まれるインタラクションが得られるまで特定の時間を待つ。起こっていないからといってただちに失敗にするのではなく。おそらくはコンカレント条件において役に立つだろう。

この機能は稀にしか使われない。マルチスレッドシステムをテストするより良い方法を見出してほしい。

これをInOrder検証と共に使うことは未実装である。

Examples:


//指定された時間にsomeMethod()が呼び出されればパス verify(mock, timeout(100)).someMethod(); //上は以下と同じである。 verify(mock, timeout(100).times(1)).someMethod(); //指定された時間内に、きっかり二回だけ呼び出されればパス verify(mock, timeout(100).times(2)).someMethod(); //指定された時間内に、少なくとも二回呼び出されればパス verify(mock, timeout(100).atLeast(2)).someMethod(); // 指定された検証モードを使って、指定時間内にsomeMethod()が呼び出されることを検証する。 // 通常は、自身のカスタム検証モードがあるときにだけ役に立つ。 verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();

23. @Spies, @InjectMocksの自動インスタンス作成と、コンストラクタインジェクション (1.9.0より)

Mockitoは@Spyのインスタンス作成を行い、@InjectMoksのフィールドをコンストラクタインジェクション、セッターインジェクション、フィールドインジェクションを使用してインスタンス作成する。

この機能の優位性を利用するために、 MockitoAnnotations.initMocks(Object)、MockitoJUnitRunner または MockitoRuleを利用すること。

※訳注:テスト前にMockitoAnnotations.initMocks(Object)を呼び出せばよい。

これについては、InjectMocksのJavaDocを見てほしい。

 //こうではなく
 @Spy BeerDrinker drinker = new BeerDrinker();
 //こう書く
 @Spy BeerDrinker drinker;

 //同じことが @InjectMocks にも適用される。
 @InjectMocks LocalPub;

24. 一行スタブ (1.9.0より)

Mockitoは、スタブ化のときにモックを作ることができる。基本的にこれは、プログラムコードの一行でスタブを作り出すものである。これはコードをクリーンにしておくのに役立つ。例えば、テストの中で決まりきったスタブを作成し、スタブ化ができる。

 public class CarTest {
   Car boringStubbedCar = when(mock(Car.class).shiftGear()).thenThrow(EngineNotStarted.class).getMock();

   @Test public void should... {}

25. 検証を無視するスタブ (1.9.0より)

Mockitoは、検証のためにスタブ化を無視することを許す。verifyNoMoreInteractions()や inOrder()による検証の際に有用になることがある。スタブ化された呼び出しについて冗長な検証を避けるようにできるのだ。典型的には、スタブを検証することに興味は無い。

警告:ignoreStubs() はverifyNoMoreInteractions(ignoreStubs(…))の使い過ぎに導くかもしれない。心に留めておくべきは、Mokcitoは推奨しないことだ、あらゆるテストをverifyNoMoreInteractions() だらけにすることを。これは、verifyNoMoreInteractions(Object…)のJavaDocに記述したことだ。

以下に例を示す。

 verify(mock).foo();
 verify(mockTwo).bar();

 //すべてのスタブ化されたメソッドを無視する。
 verifyNoMoreInteractions(ignoreStubs(mock, mockTwo));

 //スタブ化を無視するInOrderを作成する。
 InOrder inOrder = inOrder(ignoreStubs(mock, mockTwo));
 inOrder.verify(mock).foo();
 inOrder.verify(mockTwo).bar();
 inOrder.verifyNoMoreInteractions();

より高度なサンプルと詳細については、ignoreStubs(Object…)のJavaDocを参照して欲しい。

26. モック化の詳細 (2.2.xで改善)

Mockitoはモックオブジェクトの詳細を調査するAPIを提供する。このAPIは、上級ユーザやモックフレームワークインテグレータに役に立つものだ。

   //あるオブジェクトがモックなのかspyなのかを特定する。
   Mockito.mockingDetails(someObject).isMock();
   Mockito.mockingDetails(someObject).isSpy();

   //タイプやデフォルトアンサーといった詳細を取得する
   MockingDetails details = mockingDetails(mock);
   details.getMockCreationSettings().getTypeToMock();
   details.getMockCreationSettings().getDefaultAnswer();

   //モックのインタラクションやスタビングを取得する
   MockingDetails details = mockingDetails(mock);
   details.getInteractions();
   details.getStubbings();

   //すべてのインタラクションを印字する(スタビングや未使用スタブも含む)
   System.out.println(mockingDetails(mock).printInvocations());

詳細については、MockingDetails. のJavaDocを参照してほしい。

27. リアルインスタンスに呼び出しを移譲する(1.9.5より)

通常のspy-APIの使用ではモック化やspyが難しいようなオブジェクトのspyと部分モックに有用である。Mockito 1.10.11より、移譲はモックと同じタイプであっても無くても良くなった。タイプが異なる場合、マッチするメソッドが移譲に必要であり、そうでなければ例外が発生する。この機能の利用が考えられるケースとしては。

  • インターフェース付きのfinalクラス
  • 既にカスタムプロキシが作成されたオブジェクト
  • finalizeメソッドのある特別なオブジェクト。つまり、それが二回実行されてしまうのを避ける。

通常のspyでは、spyされたオブジェクトのすべての状態を含み、メソッドはスパイ上で呼び出される。spyされるインスタンスは、モック生成時にのみ、状態を取得するために試用される。もし、通常のspyのメソッドを呼び出した場合、内部的にはこのスパイの別のメソッドを呼び出す。これらの呼び出しが、検証のために記憶され、効率的にスタブ化されうる。

移譲するモックは単純にすべてのメソッドを移譲先に移譲する。メソッドがそれに移譲されると、いつでも移譲先が使用される。もしこのモックのメソッドを呼び出すと、内部的には、このモックの別のメソッドを呼び出す。これらの呼び出しは検証のための記憶がされない。スタブ化もこれらには影響を与えない。移譲するモックは、通常のspyよりもパワフルではないが、通常のspyが作れない時に有用だ。

詳細は、AdditionalAnswers.delegatesTo(Object)のドキュメントを見てほしい。

28. MockMaker API (Since 1.9.5)

Google Androidの連中からの要望によって、Mockitoは今やプロキシ生成エンジンを置き換えることができるようになった。デフォルトでは、動的プロキシの作成にMockitoはByte Buddyを使用する。

拡張ポイントはMockitoを拡張したい上級ユーザのためのものである。例えば、今やdexmakerの助けを借りて、MockitoをAndroidのテストに用いることができる。

詳細、モチベーション、例については、MockMakerのドキュメントを見てほしい。

29. BDDスタイルの検証 (Since 1.10.0)

ビヘイビア駆動開発(BDD)スタイルの検証を有効にする。BDD用thenキーワードを使用する。

 given(dog.bark()).willReturn(2);

 // when
 ...

 then(person).should(times(2)).ride(bike);

詳細と例は、BDDMockito.then(Object)}を参照して欲しい。

30. Spying or mocking abstract classes (Since 1.10.12, further enhanced in 2.7.13 and 2.7.14)

It is now possible to conveniently spy on abstract classes. Note that overusing spies hints at code design smells (see spy(Object)).

Previously, spying was only possible on instances of objects. New API makes it possible to use constructor when creating an instance of the mock. This is particularly useful for mocking abstract classes because the user is no longer required to provide an instance of the abstract class. At the moment, only parameter-less constructor is supported, let us know if it is not enough.

 //convenience API, new overloaded spy() method:
 SomeAbstract spy = spy(SomeAbstract.class);

 //Mocking abstract methods, spying default methods of an interface (only available since 2.7.13)
 Function function = spy(Function.class);

 //Robust API, via settings builder:
 OtherAbstract spy = mock(OtherAbstract.class, withSettings()
    .useConstructor().defaultAnswer(CALLS_REAL_METHODS));

 //Mocking an abstract class with constructor arguments (only available since 2.7.14)
 SomeAbstract spy = mock(SomeAbstract.class, withSettings()
   .useConstructor("arg1", 123).defaultAnswer(CALLS_REAL_METHODS));

 //Mocking a non-static inner abstract class:
 InnerAbstract spy = mock(InnerAbstract.class, withSettings()
    .useConstructor().outerInstance(outerInstance).defaultAnswer(CALLS_REAL_METHODS));

For more information please see MockSettings.useConstructor(Object…).

31. Mockito mocks can be serialized / deserialized across classloaders (Since 1.10.0)

Mockito introduces serialization across classloader. Like with any other form of serialization, all types in the mock hierarchy have to serializable, inclusing answers. As this serialization mode require considerably more work, this is an opt-in setting.

// use regular serialization
mock(Book.class, withSettings().serializable());

// use serialization across classloaders
mock(Book.class, withSettings().serializable(ACROSS_CLASSLOADERS));

For more details see MockSettings.serializable(SerializableMode).

32. Better generic support with deep stubs (Since 1.10.0)

Deep stubbing has been improved to find generic information if available in the class. That means that classes like this can be used without having to mock the behavior.

class Lines extends List {
// …
}

lines = mock(Lines.class, RETURNS_DEEP_STUBS);

// Now Mockito understand this is not an Object but a Line
Line line = lines.iterator().next();

Please note that in most scenarios a mock returning a mock is wrong.

33. Mockito JUnit rule (Since 1.10.17)

Mockito now offers a JUnit rule. Until now in JUnit there were two ways to initialize fields annotated by Mockito annotations such as @Mock, @Spy, @InjectMocks, etc.

Annotating the JUnit test class with a @RunWith(MockitoJUnitRunner.class)
Invoking MockitoAnnotations.initMocks(Object) in the @Before method

Now you can choose to use a rule :

@RunWith(YetAnotherRunner.class)
public class TheTest {
@Rule public MockitoRule mockito = MockitoJUnit.rule();
// …
}

For more information see MockitoJUnit.rule().

34. Switch on or off plugins (Since 1.10.15)

An incubating feature made it’s way in mockito that will allow to toggle a mockito-plugin. More information here PluginSwitch.

35. カスタム検証失敗メッセージ (Since 2.1.0)

検証失敗のときのカスタムメッセージを指定することができる。

例:

 // 検証失敗時にカスタムメッセージを表示する
 verify(mock, description("これが失敗時に表示される")).someMethod();

 // いかなる検証モードでも利用可能だ
 verify(mock, times(2).description("someMethodは二回呼び出されないといけない")).someMethod();

36. Java 8のラムダマッチャーのサポート(2.1.0より)

ArgumentCaptorへの依存を減らすために、ArgumentMatcherにJava 8のラムダ式を使うことができる。モックのファンクションへの入力が正しいか検証したい場合には、通常はArgumentCaptorを使ってそのオペランドを見つけ出してアサーションを行うだろう。複雑な例の場合には、これが役に立つのだが、同時にくどいことでもある。

マッチを表現するラムダを書くことは極めて簡単だ。argThatと共に使った場合、ファンクションへの引数は、ArgumentMatcherに強く型付けされたオブジェクトとして渡される。したがって、それに対して何でもすることができるのだ。

例を示す。

 // listが、それにaddされた特定の長さの文字列のみを持つかを検証する。
 // これはJava 8でのみコンパイル可能
 verify(list, times(2)).add(argThat(string -> string.length() < 5));

 // Java 7で同じことをする場合
 verify(list, times(2)).add(argThat(new ArgumentMatcher(){
     public boolean matches(String arg) {
         return arg.length() < 5;
     }
 }));

 // より複雑なJava 8の例。より複雑な検証をファンクション的に行うことができる。
 verify(target, times(1)).receiveComplexObject(argThat(obj -> obj.getSubObject().get(0).equals("expected")));

 // これは、また異なる入力でのモックの振る舞いを定義するときに使用することができる。
 // この場合には、リストへの入力が三つ未満の場合にはnullを返す。
 when(mock.someMethod(argThat(list -> list.size()<3))).willReturn(null);

37. Java 8のカスタムアンサーサポート (2.1.0より)

Answerインターフェースには唯一つのメソッドがあり、これはJava 8においてラムダ式を使用して実装可能である、非常に単純な状況において。メソッド呼び出しのパラメータを使う必要があればあるほど、InvocationMockからの引数について型キャストする必要にせまられるだろう。

例を示す。

 // いつも12を返す
 doAnswer(invocation -> 12).when(mock).doSomething();

 // パラメータの一つを使って応答する。適切な型に変換すること。
 // このケースの場合、答えとして二番目の文字列の長さを返している。
 // これで、長ったらしいパラメータのキャストを、手早くすることができる。
 doAnswer(invocation -> ((String)invocation.getArgument(1)).length())
     .when(mock).doSomething(anyString(), anyString(), anyString());

完全のために、カスタムアンサー・アクションを書けるようになっている。これは、メソッド呼び出しへのパラメータを使うものだ、Java 8のラムダ式として。Java 7あるいはそれ以前でも型インターフェースに基づくカスタムアンサーはボイラープレートを削減できる。

特に、このアプローチは、コールバックを使う関数のテストを容易にするだろう。ansertおよびAnswerVoidメソッドを使って、アンサーを作ることができる。これらは、関連するanswerインターフェースに依存している。これは、org.mockito.stubbingにあり、パラメータ数が5つまでのアンサーをサポートしている。

例を示す。

 // モックするインターフェースが次のような関数を持つとする
 void execute(String operand, Callback callback);

 // 例とするコールバックは次の関数であり、テスト下のクラスはコールバックが
 // なされることに依存するものとする
 void receive(String item);

 // Java 8 のスタイル1
 doAnswer(AdditionalAnswers.answerVoid((operand, callback) -> callback.receive("dummy"))
     .when(mock).execute(anyString(), any(Callback.class));

 // Java 8 のスタイル2。AdditionalAnswersのstaticなインポートがされているものとする
 doAnswer(answerVoid((String operand, Callback callback) -> callback.receive("dummy"))
     .when(mock).execute(anyString(), any(Callback.class));

 // Java 8 のスタイル3.モック対象関数は、テスト対象クラスのstaticメンバーであるとする
 private static void dummyCallbackImpl(String operation, Callback callback) {
     callback.receive("dummy");
 }

 doAnswer(answerVoid(TestClass::dummyCallbackImpl)
     .when(mock).execute(anyString(), any(Callback.class));

 // Java 7
 doAnswer(answerVoid(new VoidAnswer2() {
     public void answer(String operation, Callback callback) {
         callback.receive("dummy");
     }})).when(mock).execute(anyString(), any(Callback.class));

 // anwer()関数とvoideでないバージョンの関数インターフェースによって値を返すことが可能。であるから、モックインターフェースが次のようなメソッドを持つ場合。。
 boolean isSameString(String input1, String input2);

 // このようにモックが作れる
 // Java 8
 doAnswer(AdditionalAnswers.answer((input1, input2) -> input1.equals(input2))))
     .when(mock).execute(anyString(), anyString());

 // Java 7
 doAnswer(answer(new Answer2() {
     public String answer(String input1, String input2) {
         return input1 + input2;
     }})).when(mock).execute(anyString(), anyString());

38. Meta data and generic type retention (Since 2.1.0)

Mockito now preserves annotations on mocked methods and types as well as generic meta data. Previously, a mock type did not preserve annotations on types unless they were explicitly inherited and never retained annotations on methods. As a consequence, the following conditions now hold true:

@MyAnnotation
class Foo {
List bar() { … }
}

Class<?> mockType = mock(Foo.class).getClass();
assert mockType.isAnnotationPresent(MyAnnotation.class);
assert mockType.getDeclaredMethod(“bar”).getGenericReturnType() instanceof ParameterizedType;

When using Java 8, Mockito now also preserves type annotations. This is default behavior and might not hold if an alternative MockMaker is used.

39. Mocking final types, enums and final methods (Since 2.1.0)

Mockito now offers an Incubating, optional support for mocking final classes and methods. This is a fantastic improvement that demonstrates Mockito’s everlasting quest for improving testing experience. Our ambition is that Mockito “just works” with final classes and methods. Previously they were considered unmockable, preventing the user from mocking. We already started discussing how to make this feature enabled by default. Currently, the feature is still optional as we wait for more feedback from the community.

This alternative mock maker which uses a combination of both Java instrumentation API and sub-classing rather than creating a new class to represent a mock. This way, it becomes possible to mock final types and methods.

This mock maker is turned off by default because it is based on completely different mocking mechanism that requires more feedback from the community. It can be activated explicitly by the mockito extension mechanism, just create in the classpath a file /mockito-extensions/org.mockito.plugins.MockMaker containing the value mock-maker-inline.

As a convenience, the Mockito team provides an artifact where this mock maker is preconfigured. Instead of using the mockito-core artifact, include the mockito-inline artifact in your project. Note that this artifact is likely to be discontinued once mocking of final classes and methods gets integrated into the default mock maker.

Some noteworthy notes about this mock maker:

Mocking final types and enums is incompatible with mock settings like :
    explicitly serialization support withSettings().serializable()
    extra-interfaces withSettings().extraInterfaces()
Some methods cannot be mocked
    Package-visible methods of java.*
    native methods
This mock maker has been designed around Java Agent runtime attachment ; this require a compatible JVM, that is part of the JDK (or Java 9 VM). When running on a non-JDK VM prior to Java 9, it is however possible to manually add the Byte Buddy Java agent jar using the -javaagent parameter upon starting the JVM.

If you are interested in more details of this feature please read the javadoc of org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker

40. (new) Improved productivity and cleaner tests with “stricter” Mockito (Since 2.+)

To quickly find out how “stricter” Mockito can make you more productive and get your tests cleaner, see:

Strict stubbing with JUnit Rules - MockitoRule.strictness(Strictness) with Strictness.STRICT_STUBS
Strict stubbing with JUnit Runner - MockitoJUnitRunner.StrictStubs
Strict stubbing if you cannot use runner/rule (like TestNG) - MockitoSession
Unnecessary stubbing detection with MockitoJUnitRunner
Stubbing argument mismatch warnings, documented in MockitoHint

Mockito is a “loose” mocking framework by default. Mocks can be interacted with without setting any expectations beforehand. This is intentional and it improves the quality of tests by forcing users to be explicit about what they want to stub / verify. It is also very intuitive, easy to use and blends nicely with “given”, “when”, “then” template of clean test code. This is also different from the classic mocking frameworks of the past, they were “strict” by default.

Being “loose” by default makes Mockito tests harder to debug at times. There are scenarios where misconfigured stubbing (like using a wrong argument) forces the user to run the test with a debugger. Ideally, tests failures are immediately obvious and don’t require debugger to identify the root cause. Starting with version 2.1 Mockito has been getting new features that nudge the framework towards “strictness”. We want Mockito to offer fantastic debuggability while not losing its core mocking style, optimized for intuitiveness, explicitness and clean test code.

Help Mockito! Try the new features, give us feedback, join the discussion about Mockito strictness at GitHub issue 769.

41. (new) Advanced public API for framework integrations (Since 2.10.+)

In Summer 2017 we decided that Mockito should offer better API for advanced framework integrations. The new API is not intended for users who want to write unit tests. It is intended for other test tools and mocking frameworks that need to extend or wrap Mockito with some custom logic. During the design and implementation process (issue 1110) we have developed and changed following public API elements:

New MockitoPlugins - Enables framework integrators to get access to default Mockito plugins. Useful when one needs to implement custom plugin such as MockMaker and delegate some behavior to the default Mockito implementation.
New MockSettings.build(Class) - Creates immutable view of mock settings used later by Mockito. Useful for creating invocations with InvocationFactory or when implementing custom MockHandler.
New MockingDetails.getMockHandler() - Other frameworks may use the mock handler to programmatically simulate invocations on mock objects.
New MockHandler.getMockSettings() - Useful to get hold of the setting the mock object was created with.
New InvocationFactory - Provides means to create instances of Invocation objects. Useful for framework integrations that need to programmatically simulate method calls on mock objects.
New MockHandler.getInvocationContainer() - Provides access to invocation container object which has no methods (marker interface). Container is needed to hide the internal implementation and avoid leaking it to the public API.
Changed Stubbing - it now extends Answer interface. It is backwards compatible because Stubbing interface is not extensible (see NotExtensible). The change should be seamless to our users.
Deprecated InternalMockHandler - In order to accommodate API changes we needed to deprecate this interface. The interface was always documented as internal, we don't have evidence it was used by the community. The deprecation should be completely seamless for our users.
NotExtensible - Public annotation that indicates to the user that she should not provide custom implementations of given type. Helps framework integrators and our users understand how to use Mockito API safely.

Do you have feedback? Please leave comment in issue 1110.

42. (new) New API for integrations: listening on verification start events (Since 2.11.+)

Framework integrations such as Spring Boot needs public API to tackle double-proxy use case (issue 1191). We added:

New VerificationStartedListener and VerificationStartedEvent enable framework integrators to replace the mock object for verification. The main driving use case is Spring Boot integration. For details see Javadoc for VerificationStartedListener.
New public method MockSettings.verificationStartedListeners(VerificationStartedListener...) allows to supply verification started listeners at mock creation time.
New handy method MockingDetails.getMock() was added to make the MockingDetails API more complete. We found this method useful during the implementation.

43. (new) New API for integrations: MockitoSession is usable by testing frameworks (Since 2.15.+)

MockitoSessionBuilder and MockitoSession were enhanced to enable reuse by testing framework integrations (e.g. MockitoRule for JUnit):

MockitoSessionBuilder.initMocks(Object...) allows to pass in multiple test class instances for initialization of fields annotated with Mockito annotations like Mock. This method is useful for advanced framework integrations (e.g. JUnit Jupiter), when a test uses multiple, e.g. nested, test class instances.
MockitoSessionBuilder.name(String) allows to pass a name from the testing framework to the MockitoSession that will be used for printing warnings when Strictness.WARN is used.
MockitoSessionBuilder.logger(MockitoSessionLogger) makes it possible to customize the logger used for hints/warnings produced when finishing mocking (useful for testing and to connect reporting capabilities provided by testing frameworks such as JUnit Jupiter).
MockitoSession.setStrictness(Strictness) allows to change the strictness of a MockitoSession for one-off scenarios, e.g. it enables configuring a default strictness for all tests in a class but makes it possible to change the strictness for a single or a few tests.
MockitoSession.finishMocking(Throwable) was added to avoid confusion that may arise because there are multiple competing failures. It will disable certain checks when the supplied failure is not null.

44. Deprecated org.mockito.plugins.InstantiatorProvider as it was leaking internal API. it was replaced by org.mockito.plugins.InstantiatorProvider2 (Since 2.15.4)

InstantiatorProvider returned an internal API. Hence it was deprecated and replaced by InstantiatorProvider2. Old instantiator providers will continue to work, but it is recommended to switch to the new API.

45. (new) New JUnit Jupiter (JUnit5+) extension

For integration with JUnit Jupiter (JUnit5+), use the org.mockito:mockito-junit-jupiter artifact. For more information about the usage of the integration, see the JavaDoc of MockitoExtension.