2013-04-04 64 views
0

我目前正在嘗試使用PowerMock 1.4.10對一些遺留代碼進行一些單元測試,並且有一種方法是我試圖測試有靜態無效調用和靜態非無效調用。有沒有辦法在抑制靜態void調用的同時模擬靜態非void調用?抑制一個無效的靜態方法和與PowerMock在同一類中的靜態方法

@RunWith(PowerMockRunner.class) 
@PrepareForTest(ClassUnderTest.class) 
public class TestClass { 

    @Test 
    public void test() { 
     MemberModifier.suppress(StaticClass.class.getDeclaredMethod("logRandom")); 

     PowerMock.mockStatic(StaticClass.class); 
     expect(StaticClass.isLogOn()).andReturn(true); 
     PowerMock.replay(StaticClass.class); 

     ClassUnderTest test = new ClassUnderTest(); 
     test.methodToTest(); 

     assertTrue(test.tested); 

     PowerMock.verify(StaticClass.class); 
    } 
} 


public class ClassUnderTest { 
    public boolean tested = false; 

    public void methodToTest() { 
     if (StaticClass.isLogOn()) { 
      StaticClass.logRandom(); 
     } 
    } 

} 

public class StaticClass { 

    public static void logRandom() { 
     System.out.println("Do something"); 
    } 

    public static boolean isLogOn() { 
     return (Math.random() > .5); 
    } 
} 

但是,當我嘗試這樣做,我得到以下堆棧跟蹤:

java.lang.IllegalStateException: no last call on a mock available 
    at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521) 
    at org.easymock.EasyMock.expect(EasyMock.java:499) 
    at TestClass.test(TestClass.java:20) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:307) 
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88) 
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) 
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86) 
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120) 
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33) 
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45) 
    at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118) 
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102) 
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

是否有人在如何處理這個任何想法?

回答

1

我已經用PowerMock和Mockito的組合PowerMockito成功測試了靜態。你可以用PowerMockito.mockStatic而不是PowerMock版本來嘲弄你的靜態調用。完成後,您可以撥打Mockito.when來處理該呼叫。

PowerMockito.mockStatic(StaticClass.class); 
Mockito.when(StaticClass.isLogOn()).thenReturn(true); 

當測試運行時,當它到達的if (StaticClass.isLogOn()) {測試執行時,嘲笑應該介入並返回true,這踢入邏輯用於調用logRandom。從這裏,你可以嘗試使用spy來讓它調用實際的代碼,或者你可以根據需要嘲笑那個logRandom調用。你可以使用spyPowerMocktio Page下的Partial Mocking找到更多關於模擬的信息。