最初に、静的メソッド( commit )でデモクラスを作成します。
public class ClassStatic { static String getValue() { return "value"; } static String getValue(final String s) { return getValue() + s; } }
静的メソッドの簡単なテストを追加します。 これを行うには、ClassStaticTest( commit )クラスを作成します。
import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @Test(groups = {"static", "noMock"}) public class ClassStaticTest { @DataProvider public Object[][] data() throws Exception { return new Object[][]{{"", "value"}, {"test", "valuetest"}}; } @Test public void testGetValueVoid() throws Exception { Assert.assertEquals(ClassStatic.getValue(), "value"); } @Test(dataProvider = "data", dependsOnMethods = {"testGetValueVoid"}) public void testGetValueAttribute(final String v, final String r) throws Exception { Assert.assertEquals(ClassStatic.getValue(v), r); } }
この瞬間まで、PowerMockは必要なかったため、PowerMockを使用したことがありません。 次に、静的メソッドの「スタブ」を作成するために、テストクラスの「バックボーン」を作成します。
import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.IObjectFactory; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; @Test(groups = {"static", "mock"}) public class ClassStaticMockTest { @ObjectFactory public IObjectFactory setObjectFactory() { return new PowerMockObjectFactory(); } }
ClassStaticMockTestクラスを作成し、TestNGのObject Factoryを再定義しました( ドキュメント )
静的メソッドのスタブを使用してテストを追加します。
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.Assert; import org.testng.IObjectFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; import static org.mockito.MockitoAnnotations.Mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @Test(groups = {"static", "mock"}) @PrepareForTest({ClassStatic.class}) public class ClassStaticMockTest { @Mock public ClassStatic classStatic; @DataProvider public Object[][] data() throws Exception { return new Object[][]{{"", "newValue"}, {"test", "newValuetest"}}; } @ObjectFactory public IObjectFactory setObjectFactory() { return new PowerMockObjectFactory(); } @Test(dependsOnGroups = {"noMock"}) public void mockGetValueVoid() throws Exception { mockStatic(ClassStatic.class); when(ClassStatic.getValue()).thenReturn("newValue"); Assert.assertEquals(ClassStatic.getValue(), "newValue"); } }
最後の「コード」がありました-ハイブリッドテストでは、ある静的メソッドの呼び出しが「スタブ」によってブロックされ、別の静的メソッドの呼び出しは実際の呼び出しが行われます( commit )。
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.Assert; import org.testng.IObjectFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; import static org.mockito.MockitoAnnotations.Mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; /** Created by borz on 06.07.13. */ @Test(groups = {"static", "mock"}) @PrepareForTest({ClassStatic.class}) public class ClassStaticMockTest { @Mock public ClassStatic classStatic; @DataProvider public Object[][] data() throws Exception { return new Object[][]{{"", "newValue"}, {"test", "newValuetest"}}; } @ObjectFactory public IObjectFactory setObjectFactory() { return new PowerMockObjectFactory(); } @Test(dependsOnGroups = {"noMock"}) public void mockGetValueVoid() throws Exception { mockStatic(ClassStatic.class); when(ClassStatic.getValue()).thenReturn("newValue"); Assert.assertEquals(ClassStatic.getValue(), "newValue"); } @Test(dataProvider = "data", dependsOnMethods = {"mockGetValueVoid"}) public void testGetValueAttribute(final String v, final String r) throws Exception { mockStatic(ClassStatic.class); when(ClassStatic.getValue()).thenReturn("newValue"); when(ClassStatic.getValue(v)).thenCallRealMethod(); Assert.assertEquals(ClassStatic.getValue(v), r); } }
getValue()
メソッドの呼び出しをオーバーライドし、
getValue(String value)
が呼び出されると、クラスの実際のメソッドが呼び出され、既に内部で
getValue()
呼び出されていることを示します。
静的メソッドの呼び出しのシミュレーションを使用する必要性の「生きた」例として、他のクラス/メソッドをテストするときにこれらのメソッドを「スタブ」と「オーバーラップ」します( commit )。
静的メソッド
ClassStatic.getValue()
を使用するクラスを追加します。
public class ClassUseStatic { public String getValue() { return ClassStatic.getValue() + "noStatic"; } }
そして、
ClassStatic.getValue()
呼び出しをオーバーライドする
ClassUseStatic.getValue()
メソッドのテストを追加します。
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.Assert; import org.testng.IObjectFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test; import static org.mockito.MockitoAnnotations.Mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @Test(groups = {"useStatic", "mock"}, dependsOnGroups = {"static"}) @PrepareForTest({ClassStatic.class}) public class ClassUseStaticTest { @Mock public ClassStatic classStatic; @DataProvider public Object[][] data() throws Exception { return new Object[][]{{"newValue1", "newValue1noStatic"}, {"newValue2", "newValue2noStatic"}}; } @ObjectFactory public IObjectFactory setObjectFactory() { return new PowerMockObjectFactory(); } @Test(dataProvider = "data") public void testGetValue(String value, String result) throws Exception { mockStatic(ClassStatic.class); when(ClassStatic.getValue()).thenReturn(value); ClassUseStatic testClass = new ClassUseStatic(); Assert.assertEquals(result, testClass.getValue()); } }
PS:すべての例はGitHubにあります 。
UPD:「通常の」クラスをテストするときに静的メソッドの呼び出しをシミュレートする例を追加しました。