MockitoはモックをInjectしてこそかなーと
Mockito(モヒート、モック伊藤)はJavaのモックライブラリです。モックオブジェクトを作成してユニットテストに利用することができます。
今回Mockitoを使ったり調べたりするうちに、いくつかのMockitoのサンプルコードに対して、「Injectionは?Injectionはどうするの?え?setter?」と思ったので、自分でサンプルコードを書いてみることにしました。
よくあるサンプルコード
例1
@RunWith(JUnit4.class) public class HogeTest { @Test public void test_hoge() { List list = mock(List.class); when(list.size()).thenReturn(10); // 検証 assertThat(list.size(), is(10)); } }
例2
@RunWith(JUnit4.class) public class HogeTest { @Test public void test_hoge() { List list = mock(List.class); when(list.size()).thenReturn(10); Hoge hoge = new Hoge(); hoge.setList(list); // 実行 hoge.doSomething(); // 検証 assertThat(list.size(), is(10)); } }
良くこんな感じのサンプルを見かけます。もちろん言いたいことは分かりますし、Mockitoにちょっと触れてみるには良いと思います。
ですが、いくつか問題があるな、と思いました。
サンプルの問題
- 例1は、単にMockitoの機能のテストをしているにすぎない
- 例2は、MockオブジェクトをInjectする方法がsetterなので、setterがないときどうするのか不明
自分が考えるMockitoのサンプルコード
テストコード
package com.tsukaby.sample; import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @RunWith(JUnit4.class) public class HogeTest { @Mock(name = "nameList") private List list; @InjectMocks private Hoge hoge = new Hoge(); @Before public void setup() { MockitoAnnotations.initMocks(this); } @Test public void test_hoge() { // 実行 hoge.doSomething(); // 検証 Mockito.verify(list).addAll(Mockito.anyCollection()); } }
Hogeクラス
package com.tsukaby.sample; import java.util.ArrayList; import java.util.List; public class Hoge { private List<String> nameList = new ArrayList<String>(); public void doSomething() { nameList.addAll(getDatabaseValues()); System.out.println(nameList); } private List<String> getDatabaseValues() { // 実際は色々処理する List<String> list = new ArrayList<String>(); list.add("Taro"); list.add("Jiro"); list.add("Saburo"); return list; } }
Mockito、モックによるテストのポイント
- Injectionはアノテーションで行う
これで注入先がfieldならsetterが無くてもOKです。ローカル変数に注入したいケースもあるかもしれませんが、自分が調べた限り無理そうな感じです。 - 検証はverifyが基本、モックオブジェクトにどういうことが起きたかを検証する
これでモックオブジェクトに対してテスト対象のクラスがどういうことをしたかが検証できます。assertThatではできないことができます。
自分の認識ではモックでもスタブと同じことができます。thenReturnとかで。ただそれは本質ではない・・と。モックの本質はモックオブジェクトに対してどのようなことが起きたかを検証することなのではないかなーと。
以上です。