PowerMock + Mockito を使ってみる

PowerMock + Mockito を簡単に使ってみたのでメモを残しておきます。

やったこととしては、

1. static メソッドのモック化
2. private メソッドのモック化
3. 例外投げるメソッドのモック化
4. コンストラクタのモック化

という感じです。

今回は、Maven 使ってやることにしました。pom.xml の記述内容は以下に。

・Mockito_maven - powermock - PowerMock is a Java framework that allows you to unit test code normally regarded as untestable. - Google Project Hosting
https://code.google.com/p/powermock/wiki/Mockito_maven

※ 以下から .jar をダウンロードしてもいいです。

・Downloads - powermock - PowerMock is a Java framework that allows you to unit test code normally regarded as untestable. - Google Project Hosting
https://code.google.com/p/powermock/wiki/Downloads?tm=2


細かい説明はドキュメントに譲って、とりあえずテスト対象コード、テストケースを並べます。

1. static メソッドのモック化


* テスト対象コード

package sample;

public class StaticSample {
    public static String staticMethod(String s) {
        String result = null;
        // something ...
        return result;
    }
}

テストケース

package sample;

import junit.framework.TestCase;

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

@RunWith(PowerMockRunner.class)
@PrepareForTest(StaticSample.class)
public class StaticSampleTest extends TestCase {

  @Test
  public void staticMethodTest() {
    PowerMockito.mockStatic(StaticSample.class);
    Mockito.when(StaticSample.staticMethod("hoge")).thenReturn("staticMethod hoge");
    Mockito.when(StaticSample.staticMethod("uga")).thenReturn("staticMethod uga");

    String r1 = StaticSample.staticMethod("hoge");
    String r2 = StaticSample.staticMethod("uga");

    PowerMockito.verifyStatic(Mockito.times(1));
    StaticSample.staticMethod("hoge");

    PowerMockito.verifyStatic(Mockito.times(1));
    StaticSample.staticMethod("uga");

    assertEquals("staticMethod hoge", r1);
    assertEquals("staticMethod uga", r2);
  }
}


もちろん以下みたいに部分的にモック化するコードでも大丈夫。

 ( 略 )
  @Test
  public void staticMethodTest2() throws Exception {
    PowerMockito.spy(StaticSample.class);
    PowerMockito.when(StaticSample.class, "staticMethod", "oro").thenReturn("staticMethod oro");
    
    String r = StaticSample.staticMethod("oro");
    
    PowerMockito.verifyStatic(Mockito.times(1));
    StaticSample.staticMethod("oro");
    
    assertEquals("staticMethod oro", r);
  }
 ( 略 )


2. private メソッドのモック化


* テスト対象コード

package sample;

public class PrivateSample {
    private int privateMethod(int i) {
        int result = 0;
        // something
        return result;
    }
    
    public int test(int i) {
        return privateMethod(i);
    }
}

テストケース

package sample;

import junit.framework.TestCase;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.membermodification.MemberMatcher;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(PrivateSample.class)
public class PrivateSampleTest extends TestCase {

    @Test
    public void privateMethodTest() throws Exception {
        PrivateSample instance = PowerMockito.spy(new PrivateSample());
        PowerMockito.when(instance, "privateMethod", 1).thenReturn(100);
        PowerMockito
                .when(instance,
                        MemberMatcher.method(PrivateSample.class,
                                "privateMethod", int.class)).withArguments(2).thenReturn(200);

        int r1 = instance.test(1);
        int r2 = instance.test(2);

        PowerMockito.verifyPrivate(instance, Mockito.times(1)).invoke("privateMethod", 1);
        PowerMockito.verifyPrivate(instance, Mockito.times(1)).invoke("privateMethod", 2);
        
        assertEquals(100, r1);
        assertEquals(200, r2);
    }
}


3. 例外投げるメソッドのモック化


* テスト対象コード

package sample;

public class ExThrowSample {
    public void exThrowMethod() throws Exception {
        // something...
    }
}

テストケース

package sample;

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

@RunWith(PowerMockRunner.class)
@PrepareForTest(ExThrowSample.class)
public class ExThrowSampleTest {

    @Test(expected = Exception.class)
    public void exThrowMethodTest() throws Exception {
        ExThrowSample instance = PowerMockito.spy(new ExThrowSample());
        PowerMockito.doThrow(new Exception()).when(ExThrowSample.class);
        instance.exThrowMethod();
    }
}


4. コンストラクタのモック化


* テスト対象コード

package sample;

public class NewSample {
  public String callA() {
    return new A().a();
  }
}

// こいつがモック化の対象クラス
class A {
  public A() {
    // something...
  }

  public String a() {
    // something...
    return null;
  }
}

テストケース

package sample;

import junit.framework.TestCase;

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

@RunWith(PowerMockRunner.class)
@PrepareForTest(NewSample.class)
public class NewSampleTest extends TestCase {
  @Test
  public void newTest() throws Exception {
    A a = PowerMockito.mock(A.class);
    PowerMockito.whenNew(A.class).withNoArguments().thenReturn(a);
    PowerMockito.when(a, "a").thenReturn("aaaaa");

    NewSample ns = new NewSample();
    assertEquals("aaaaa", ns.callA());
  }
}


1、2、3 に関しては、以下のドキュメントを参考にやってます。

・MockitoUsage13 - powermock - PowerMock is a Java framework that allows you to unit test code normally regarded as untestable. - Google Project Hosting
https://code.google.com/p/powermock/wiki/MockitoUsage13

4 に関しては、ちょっとバージョンが古くメソッドとか違う感じですが、参考にしたのは以下のドキュメントです。

・MockConstructor - powermock - PowerMock is a Java framework that allows you to unit test code normally regarded as untestable. - Google Project Hosting
https://code.google.com/p/powermock/wiki/MockConstructor


かけ足ですが、以上です。

[ 環境情報 ]
Windows 7 SP1
PowerMock 1.6.2
Java SE 8 Update 25