PowerMock(+ Mockito)+ TestNGおよび(モック)静的メソッド呼び出しのシミュレーション

ハブには既にPowerMockの使用例に関する記事がありましたが、クラスの静的メソッドの一部が「スタブ」に置き換えられ、クラス内の独立した「ユニット」として、またはハイブリッド使用として静的メソッドの呼び出しをシミュレートする方法についての説明が不足しています。本当に呼ばれています。 このニッチを修正しようとします。



最初に、静的メソッド( 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:「通常の」クラスをテストするときに静的メソッドの呼び出しをシミュレートする例を追加しました。



All Articles