Mockito+PowerMockでStringのmockを作る

文字列のハッシュ衝突時のテストケースを書くことになりましたが、いつも使っているMockitoはfinal classのmockを作ることができません。

調べてみたところ、PowerMockというモジュールを使うことによって、MockitoAPIを用いてfinal classのmockを作ることができることが分かり、試してみました。

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.powermock.api.mockito.PowerMockito.*; 

@RunWith(PowerMockRunner.class)
@PrepareForTest(String.class)
public class HashCollisionTest {

    @Test
    public void testHashCodeEquivalent(){
        String foo = "foo";
        String bar = "bar";

        assertThat(foo.hashCode(), is(not(bar.hashCode())));
        
        bar = spy(bar);
        when(bar.hashCode()).thenReturn(foo.hashCode());
        
        assertThat(bar, is("bar"));
        assertThat(foo.hashCode(), is(bar.hashCode()));
    }
}

Mockitoのみを用いた場合と異なるのは以下の3点です。

  • static importの変更
    • 「org.mockito.Mockito.*」から「org.powermock.api.mockito.PowerMockito.*」に
  • @RunWith(PowerMockRunner.class)を追加
  • @PrepareForTest([mockの対象となるclass])を追加

PowerMockは既存のmockモジュールを拡張するモジュールで、EasyMockMockitoに対応しています。final classのmockを作成する為に別のmockモジュールを導入しても良いですが、既にEasyMockMockitoを使ってテストコードを書いているのであれば、PowerMockを導入してみることをお勧めします。