Java
JUnit
Mockito

Mockito1xでのケース別モックのかけかた

概要

Mockitoを使うときに、この場合はどうやったらモックをかけられるかを毎回ググっていたのですが、いい加減効率が悪いのでまとめることにしました。
本当はJMockitを使いたいのですが、黒魔術は禁止されているので、Mockitoを使います。

前提

うちはまだ2系に移行できていないので、Mockito1xが前提です。
Mockito 1.10.19
JUnit 4.11
Java 1.8.0_151

ケース

Mockitoで注意しないといけないのは、メソッドの戻り値がvoidか、そうでないかでモックのかけかたが違うということです。これを踏まえて、以下の6つに分類しました。

No モック対象メソッドの戻り型 モック範囲 モック動作
1 void以外 全体 指定した戻り値を返す
2 void以外 全体 例外を投げる
3 void 全体 例外を投げる
4 void以外 一部のメソッドのみ 指定した戻り値を返す
5 void以外 一部のメソッドのみ 例外を投げる
6 void 一部のメソッドのみ 例外を投げる

ちなみに、privateメソッド、staticメソッド、依存オブジェクトをnewで生成しているケースは、PowerMockの範囲になりますので、また別に記事書きます。
→書きました。
PowerMock+Mockito1xでのケース別モックのかけかた
https://qiita.com/taka_22/items/27ea1fbf9c305ba83dcc

テストの書き方

No.1

/**
 * publicメソッド、戻り型はvoid以外、全部モック、値を戻す
 */
@Test
public void test001() {
    List mockedList = mock(List.class);

    when(mockedList.get(0)).thenReturn("aaa");

    assertThat((String)mockedList.get(0), is("aaa"));
    assertNull(mockedList.get(1));
}

No.2

/**
 * publicメソッド、戻り型はvoid以外、全部モック、例外を投げる
 */
@Test
public void test002() {
    List mockedList = mock(List.class);

    when(mockedList.get(0)).thenThrow(new RuntimeException("aaa"));

    try {
        mockedList.get(0);
        fail();
    } catch(RuntimeException e) {
        assertThat(e.getMessage(), is("aaa"));
    }

    assertNull(mockedList.get(1));
}

No.3

doThrowが前に来るのがポイント。

/**
 * publicメソッド、戻り型はvoid、全部モック、例外を投げる
 */
@Test
public void test003() {
    List mockedList = mock(List.class);

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

    try {
        mockedList.clear();
        fail();
    } catch(RuntimeException e) {
        assertThat(e.getMessage(), is("aaa"));
    }

    assertNull(mockedList.get(0));
}

No.4

一部のみモックする場合は、mockではなくて、spyを使います。
テスト対象メソッドから呼ばれる、テスト対象でないメソッドの挙動を変えたいときなどに使います。

/**
 * publicメソッド、戻り型はvoid以外、一部モック、値を戻す
 */
@Test
public void test004() {
    List spiedList = spy(new ArrayList());

    // リアルオブジェクトには"bbb"を追加したが
    spiedList.add("bbb");
    // スパイでget(0)は"aaa"を返すようにした
    when(spiedList.get(0)).thenReturn("aaa");

    // 結果は"aaa"が得られる
    assertThat((String)spiedList.get(0), is("aaa"));
    // その他のメソッドはリアルの結果が返される
    assertThat(spiedList.size(), is(1));
}

No.5

/**
 * publicメソッド、戻り型はvoid以外、一部モック、例外を投げる
 */
@Test
public void test005() {
    List spiedList = spy(new ArrayList());

    // リアルオブジェクトには"bbb"を追加したが
    spiedList.add("bbb");
    // スパイでget(0)はRuntimeExceptionをスローするようにした
    when(spiedList.get(0)).thenThrow(new RuntimeException("aaa"));

    try {
        spiedList.get(0);
        fail();
    } catch(Exception e) {
        assertThat(e.getMessage(), is("aaa"));
    }
    // その他のメソッドはリアルの結果が返される
    assertThat(spiedList.size(), is(1));
}

No.6

/**
 * publicメソッド、戻り型はvoid、一部モック、例外を投げる
 */
@Test
public void test006() {
    List spiedList = spy(new ArrayList());

    // リアルオブジェクトには"bbb"を追加
    spiedList.add("bbb");
    // clearが呼ばれたときはRuntimeExceptionを投げる
    doThrow(new RuntimeException("aaa")).when(spiedList).clear();

    try {
        spiedList.clear();
        fail();
    } catch(RuntimeException e) {
        assertThat(e.getMessage(), is("aaa"));
    }

    // その他のメソッドはリアルの結果が返される
    assertThat(spiedList.size(), is(1));
    assertThat((String)spiedList.get(0), is("bbb"));
}

参考

Mockito

http://site.mockito.org/

動作確認したプロジェクト

https://github.com/taka2/mockito-sample

PowerMock+Mockito1xでのケース別モックのかけかた

https://qiita.com/taka_22/items/27ea1fbf9c305ba83dcc