Revision 9 as of 2009-12-10 00:19:43

Clear message
Locked History Actions

mockito/Manual

mockitoマニュアル

以下はMockitoクラスJavaDocの訳(Version 1.8.1、現在翻訳進行中)


以下の例はListをモックしているが、これは誰もがそのインターフェース(add, get, clear等のメソッド)を知っているからだ。 たぶん、実際にはListをモックすることなんかないだろうけど。

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

 //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()メソッドを使う。しかし、もっとフレキシブルな方法が必要になることもある。その場合はmatcher引数を使うことができる。

 //(Mockitoに)付属のanyInt()matcherを使ってスタブ化
 when(mockedList.get(anyInt())).thenReturn("element");
 
 //hamcrestを使ってスタブ化。ここではisValid()メソッドが、あなたの作成したhamcrest-matcherを返すものとする。
 when(mockedList.contains(argThat(isValid()))).thenReturn("element");
 
 //以下は"element"を表示する
 System.out.println(mockedList.get(999));
 
 //引数matcherを使って検証することもできる。
 verify(mockedList).get(anyInt());

引数matcherによってフレキシブルな検証とスタブ化をすることができる。 ここ にビルトインmatcher、カスタム引数matcher、hamcrest-matcherの情報がある。

カスタム引数matcherについてはArgumentMatcherを参照のこと。

複雑な引数マッチングについて妥当性を保つこと。 The natural matching style using equals() with occasional anyX() matchers tend to give clean & simple tests. 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として提供されていない。

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ファミリーを参照のこと。

初期バージョンでは、stubVoid(Object)をvoidメソッドのスタブ化に使用していた。 現在ではstubVoid()はdeprecatedとなっており、代わりにdoThrow(Throwable)を用いる。 この理由はリーダビリティの改善とdoAnswer(Answer)メソッドファミリーとの一貫性のためである。

6. 順序の検証

 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");

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

また、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() is a handy assertion from the interaction testing toolkit. Use it only when it's relevant. Abusing it leads to overspecified, less maintainable tests. You can find further reading here.

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の使用を考慮すること。 MockitoAnnotationsを参照のこと。

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

同じメソッド呼び出しに対し、異なる値を返したり異なる例外を投げたりしたい場合がある。 その典型がイテレータのモッキングである。 Mockitoのオリジナルバージョンはこのような機能を持っていなかった。 例えば、Iteratorの代わりにIterableや単純なCollectionを使いたいことがある。 Those offer natural ways of stubbing (e.g. using real collections). しかし、稀だが連続呼び出しをスタブ化できた方が便利なこともある。

 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");

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

Allows stubbing with generic Answer interface.

Yet another controversial feature which was not included in Mockito originally. We recommend using simple stubbing with thenReturn() or thenThrow() only. Those two should be just enough to test/test-drive any clean & simple code.

  • when(mock.someMethod(anyString())).thenAnswer(new Answer() {
    • Object answer(InvocationOnMock invocation) {

      • Object[] args = invocation.getArguments(); Object mock = invocation.getMock(); return "called with arguments: " + args;
      }
    }); //Following prints "called with arguments: foo" System.out.println(mock.someMethod("foo"));

12. doThrow()|doAnswer()|doNothing()|doReturn() family of methods for stubbing voids (mostly) Stubbing voids requires different approach from when(Object) because the compiler does not like void methods inside brackets...

doThrow(Throwable) replaces the stubVoid(Object) method for stubbing voids. The main reason is improved readability and consistency with the family of doAnswer() methods.

Use doThrow() when you want to stub a void method with an exception:

Read more about other methods:

doThrow(Throwable)

doAnswer(Answer)

doNothing()

doReturn(Object) 13. Spying on real objects You can create spies of real objects. When you use the spy then the real methods are called (unless a method was stubbed).

Real spies should be used carefully and occasionally, for example when dealing with legacy code.

Spying on real objects can be associated with "partial mocking" concept. Before the release 1.8, Mockito spies were not real partial mocks. The reason was we thought partial mock is a code smell. At some point we found legitimate use cases for partial mocks (3rd party interfaces, interim refactoring of legacy code, the full article is here)

  • List list = new LinkedList(); List spy = spy(list); //optionally, you can stub out some methods: when(spy.size()).thenReturn(100); //using the spy calls real methods spy.add("one"); spy.add("two"); //prints "one" - the first element of a list System.out.println(spy.get(0)); //size() method was stubbed - 100 is printed System.out.println(spy.size()); //optionally, you can verify verify(spy).add("one"); verify(spy).add("two");

Important gotcha on spying real objects! 1. Sometimes it's impossible to use when(Object) for stubbing spies. Example:

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

    //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); //You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0);

2. Watch out for final methods. Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble. What will happen is the real method will be called *on mock* but *not on the real instance* you passed to the spy() method. Typically you may get a NullPointerException because mock instances don't have fields initiated. 14. Changing default return values of unstubbed invocations (Since 1.7) You can create a mock with specified strategy for its return values. It's quite advanced feature and typically you don't need it to write decent tests. However, it can be helpful for working with legacy systems.

It is the default answer so it will be used only when you don't stub the method call.

  • Foo mock = mock(Foo.class, Mockito.RETURNS_SMART_NULLS);

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

Read more about this interesting implementation of Answer: RETURNS_SMART_NULLS 15. Capturing arguments for further assertions (Since 1.8.0) Mockito verifies argument values in natural java style: by using an equals() method. This is also the recommended way of matching arguments because it makes tests clean & simple. In some situations though, it is helpful to assert on certain arguments after the actual verification. For example:

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

Warning: it is recommended to use ArgumentCaptor with verification but not with stubbing. Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block. Also it may reduce defect localization because if stubbed method was not called then no argument is captured.

In a way ArgumentCaptor is related to custom argument matchers (see javadoc for ArgumentMatcher class). Both techniques can be used for making sure certain arguments where passed to mocks. However, ArgumentCaptor may be a better fit if:

  • custom argument matcher is not likely to be reused
  • you just need it to assert on argument values to complete verification

Custom argument matchers via ArgumentMatcher are usually better for stubbing. 16. Real partial mocks (Since 1.8.0) Finally, after many internal debates & discussions on the mailing list, partial mock support was added to Mockito. Previously we considered partial mocks as code smells. However, we found a legitimate use case for partial mocks - more reading: here

Before release 1.8 spy() was not producing real partial mocks and it was confusing for some users. Read more about spying: here or in javadoc for spy(Object) method.

  • //you can create partial mock with spy() method:

    List list = spy(new LinkedList()); //you can enable partial mock capabilities selectively on mocks: Foo mock = mock(Foo.class); //Be sure the real implementation is 'safe'. //If real implementation throws exceptions or depends on specific state of the object then you're in trouble. when(mock.someMethod()).thenCallRealMethod();

As usual you are going to read the partial mock warning: Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects. How does partial mock fit into this paradigm? Well, it just doesn't... Partial mock usually means that the complexity has been moved to a different method on the same object. In most cases, this is not the way you want to design your application.

However, there are rare cases when partial mocks come handy: dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.) However, I wouldn't use partial mocks for new, test-driven & well-designed code. 17. Resetting mocks (Since 1.8.0) Smart Mockito users hardly use this feature because they know it could be a sign of poor tests. Normally, you don't need to reset your mocks, just create new mocks for each test method.

Instead of reset() please consider writing simple, small and focused test methods over lengthy, over-specified tests. First potential code smell is reset() in the middle of the test method. This probably means you're testing too much. Follow the whisper of your test methods: "Please keep us small & focused on single behavior". There are several threads about it on mockito mailing list.

The only reason we added reset() method is to make it possible to work with container-injected mocks. See issue 55 (here) or FAQ (here).

Don't harm yourself. reset() in the middle of the test method is a code smell (you're probably testing too much).

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

    //at this point the mock forgot any interactions & stubbing

18. Troubleshooting & validating framework usage (Since 1.8.0) First of all, in case of any trouble, I encourage you to read the Mockito FAQ: http://code.google.com/p/mockito/wiki/FAQ

In case of questions you may also post to mockito mailing list: http://groups.google.com/group/mockito

Next, you should know that Mockito validates if you use it correctly all the time. However, there's a gotcha so please read the javadoc for validateMockitoUsage() 19. Aliases for behavior driven development (Since 1.8.0) 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!

Start learning about BDD here: http://en.wikipedia.org/wiki/Behavior_Driven_Development

The problem is that current stubbing api with canonical role of when word does not integrate nicely with //given //when //then comments. It's because stubbing belongs to given component of the test and not to the when component of the test. Hence BDDMockito class introduces an alias so that you stub method calls with BDDMockito.given(Object) method. Now it really nicely integrates with the given component of a BDD style test!

Here is how the test might look like:

  • 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. (**New**) Serializable mocks (Since 1.8.1) Mocks can be made serializable. With this feature you can use a mock in a place that requires dependencies to be serializable.

WARNING: This should be rarely used in unit testing.

The behaviour was implemented for a specific use case of a BDD spec that had an unreliable external dependency. This was in a web environment and the objects from the external dependency were being serialized to pass between layers.

To create serializable mock use MockSettings.serializable():

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

The mock can be serialized assuming all the normal serialization requirements are met by the class.

Making a real object spy serializable is a bit more effort as the spy(...) method does not have an overloaded version which accepts MockSettings. No worries, you will hardly ever use it.

  • List list = new ArrayList(); List spy = mock(ArrayList.class, withSettings()

    • spiedInstance(list)
    • defaultAnswer(CALLS_REAL_METHODS)
    • serializable());