29
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MockitoとEasyMockとJMockitはどれがいい?

Last updated at Posted at 2016-04-03

JUnitと一緒に使うモックライブラリで個人的にMockitoを使ってたのですが、プロジェクト内の別の人はEasyMockを使っており、どのモックライブラリが使いやすいのかなと思い、3つのライブラリを使ってみました。最後に、オススメ度をつけてますが、あくまでも個人的な見解です。

環境
Java 1.7
JUnit 4.10
JMockit 1.22
Mockito 1.10.19
EasyMock 3.4
PowerMock 1.6.4

外部インターフェースをモック化することを想定し、各ライブラリを使用してJUnitを作成しました。
テスト対象とインターフェースは下記のソースとします。

Sample.java
public class Sample {

    private CallStore store = null;

    /**
     * 電話番号を取得
     * @param name
     * @return
     */
    public String getcallNumber(String name,String area) {
        String number = store.getCallNumber(name);
        if (number == null) {
            number = "";
        } else {
            if ("Tykyo".equals(area)) {
                number = "03-" + number;
            }
        }
        return number;
    }
}
CallStore.java
interface CallStore {
    public String getCallNumber(String name);
    public String getCallArea(String area);
}

まずは、Mockitoです。
アノテーションを使うときに MockitoAnnotations.initMocks(<Class>class);
必要なのが残念な感じがします。(アノテーションを使わなければいいだけなんですけどね)
モックの定義は英文のように定義できるのでわかりやすいのではないでしょうか?
doReturn(これを返すよ).when(このオブジェクトの).このメソッドで
また、PowerMock + Mockitoによるprivateメソッドをモック化した場合、EclEmmaではカバレッジが測定されないため、カバレッジが必要な方は注意が必要です。

SampleUseMockitoTest.java
public class SampleUseMockitoTest {

    @Mock
    CallStore store;

    @InjectMocks
    Sample sut = new Sample();

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testGetCallNumber() {
        // SetUp
        Mockito.doReturn("000-1111").when(store).getCallNumber(Matchers.anyString());
        String expected = "000-1111";
        String name = "Tanaka";
        String area = "Kanagawa";

        // Test
        String actual = sut.getcallNumber(name, area);

        // Verify
        assertThat(actual, is(expected));
    }
}

続いては、EasyMock。
Mockitoとは違いアノテーションを使うときに初期化がいらないようですが、モックを有効にするためにreplay()が必要です。
モックが増えるとたくさん指定しないといけなくなるので個人的には嫌です。
モックの定義は、Mockitoとは異なり日本語のように定義できるのでEasyMockの方が定義が理解しやすいと思います。
また、PowerMock + EasyMockによるprivateメソッドをモック化した場合、EclEmmaではカバレッジが測定されないため、カバレッジが必要な方は注意が必要です。

SampleUseEasyMockTest.java
public class SampleUseEasyMockTest {

    @Rule
    public EasyMockRule mocks = new EasyMockRule(this);

    @Mock
    private CallStore store;

    @TestSubject
    private Sample sut = new Sample();

    @Test
    public void test() {
        EasyMock.expect(store.getCallNumber(EasyMock.anyString())).andReturn("000-1111");
        String expected = "000-1111";
        String name = "Tanaka";
        String area = "Kanagawa";
        EasyMock.replay(store);

        // Test
        String actual = sut.getcallNumber(name, area);

        // Verify
        assertThat(actual, is(expected));
    }
}

続いて、JMockitです。
アノテーションは初期化なしで使えます。
モック定義はブロック内でまとめて定義できるので見やすいと思います。
モックの定義も通常の定義に対してresultで期待する戻り値を記述するだけなので、特に迷うことはないと思います。(戻り値がvoidの場合は定義の仕方が変わると思います。)
また、privateメソッドをモック化した場合でも、EclEmmaでカバレッジの測定が可能なので、MockitoやEasyMockと比べてJMockitの強みだと思います。

SampleUseJMockitTest.java
@RunWith(JMockit.class)
public class SampleUseJMockitTest {

    @Injectable
    private CallStore store;

    @Tested
    private Sample sut = new Sample();

    @Test
    public void test() {
        // SetUp
        new Expectations() {{
            store.getCallNumber(anyString); result = "000-1111";
        }};
        String name = "Tanaka";
        String area = "Kanagawa";
        String expected = "000-1111";

        // Test
        String actual = sut.getcallNumber(name, area);

        // Verify
        assertThat(actual, is(expected));
    }
}

最後にオススメ度です。最初にも記述していますがあくまでも個人的な見解です。
##オススメ度
・EasyMock
オススメ度:★★☆☆☆
 モック化したオブジェクトに対してreplay()をコールしないといけない点、
 モックする場合にexpect(モック定義)で定義しなければいけない部分がマイナスだと
 思います。

・Mockito
オススメ度:★★★☆☆
 EasyMockと異なりreplay()がいらないのがよい点です。
 ただし、PowerMockを使用したときにカバレッジが測定できない点がマイナスです。

・JMockit
オススメ度:★★★★☆
 モックをブロック内で定義でき、モック定義の複雑さはMockitoと変わらないと
 思います。
 privateメソッドをモック化してもカバレッジが測定できる点は非常にプラスな点だと
 思います。ただし、学習コストが他のライブラリよりもかかるかと思います。

個人的な見解で、オススメ度を付けてみましたが、私自身もJMockitをあまり知らないのでこれから学んでみようと思います。学習する中でオススメ度は更新できたらと思います。(Theoriesランナーと同時に使用できるか気になる点でもあります。)

29
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?