2017-10-07 43 views
0

我有以下罐:PowerMockito ClassNotPreparedException

javax.servlet-api-3.1.9.jar 
junit-4.10.jar 
mockito-all-1.10.19.jar 
mockito-core-1.10.19.jar 
powermock-api-mockito-1.6.5.jar 
powermock-api-mockito-common-1.6.5.jar 
powermock-api-support-1.6.5.jar 
powermock-core-1.6.5.jar 
powermock-module-junit4-1.6.5.jar 
powermock-reflect-1.6.5.jar 

我想測試此方法稱爲createPanel這是一種稱爲Controller類中:

public static void createPanel(HttpServletRequest req, HttpServletResponse res, HttpSession hs) throws IOException 
{ 
    PanelManager.createPanel(req, res, hs); 
} 

ControllerTest類(junit的測試儀),我有這個:

import static org.mockito.Mockito.verify; 
import static org.mockito.Mockito.when; 
import java.io.IOException; 
import java.io.PrintWriter; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.Mockito; 
import org.mockito.runners.MockitoJUnitRunner; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 
import ApplicationLogic.Controller; 
import ApplicationLogic.PanelManager; 
import ApplicationLogic.RegistrationManager; 
import ApplicationLogic.SessionManager; 

@PrepareForTest(PanelManager.class) 
@RunWith(MockitoJUnitRunner.class) 

public class ControllerTest { 

    Controller controller = Mockito.mock(Controller.class); 

    SessionManager sessionManager = Mockito.mock(SessionManager.class); 

    RegistrationManager registrationManager = Mockito.mock(RegistrationManager.class); 
     . 
     . 
     . 
     . 

    @Test 

public void testcreatePanel() throws ServletException, IOException{ 

    HttpServletRequest req = Mockito.mock(HttpServletRequest.class); 
    HttpServletResponse res = Mockito.mock(HttpServletResponse.class); 
    HttpSession hs = Mockito.mock(HttpSession.class); 


    //PowerMockito.mock(SessionManager.class); 

    PrintWriter writer = new PrintWriter("somefile.txt"); 
    when(res.getWriter()).thenReturn(writer); 

    PowerMockito.mockStatic(Controller.class); 

    PowerMockito.doCallRealMethod().when(controller).createPanel(req, res, hs); 

所有的測試s在控制器類中的其他方法運行良好。爲什麼它是在PowerMockito.doCallRealMethod()導致此錯誤:

org.powermock.api.mockito.ClassNotPreparedException: 
The class ApplicationLogic.Controller not prepared for test. 
To prepare this class, add class to the '@PrepareForTest' annotation. 
In case if you don't use this annotation, add the annotation on class or method level. 

    at org.powermock.api.mockito.expectation.reporter.MockitoPowerMockReporter.classNotPrepared(MockitoPowerMockReporter.java:31) 
    at org.powermock.api.mockito.internal.mockcreation.MockTypeValidatorFactory$DefaultMockTypeValidator.validate(MockTypeValidatorFactory.java:38) 
    at org.powermock.api.mockito.internal.mockcreation.AbstractMockCreator.validateType(AbstractMockCreator.java:18) 
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMock(MockCreator.java:57) 
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:47) 
    at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:71) 
    at JUnitTest.ControllerTest.testcreatePanel(ControllerTest.java:253) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) 
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 

回答

1

您必須使用PowerMockRunner代替MockitoJUnitRuner

這個例子解決了ClassNotPreparedException

@RunWith(PowerMockRunner.class) 
@PrepareForTest({PanelManager.class}) 
public class ControllerTest { 

    Controller controller = Mockito.mock(Controller.class); 

    @Test 
    public void testcreatePanel() throws Exception { 
     HttpServletRequest req = Mockito.mock(HttpServletRequest.class); 
     HttpServletResponse res = Mockito.mock(HttpServletResponse.class); 
     HttpSession hs = Mockito.mock(HttpSession.class); 

     PrintWriter writer = new PrintWriter("somefile.txt"); 
     Mockito.when(res.getWriter()).thenReturn(writer); 

     PowerMockito.mockStatic(PanelManager.class); 
     PowerMockito.doCallRealMethod().when(controller).createPanel(req, res, hs); 
    } 
} 

但是,它看起來像有可能仍然是即使有些問題;你正在嘲笑控制器,然後通過調用doCallRealMethod()就可以將其視爲部分模擬。也許有一個真正的原因(也許因此會通過展示更多的代碼來顯示),但如果你沒有爲一個真正的理由,那麼你可以刪除此行:

Controller controller = Mockito.mock(Controller.class); 

而且替換此行...

PowerMockito.doCallRealMethod().when(controller).createPanel(req, res, hs); 

與此:

Controller.createPanel(req, res, hs); 

這則允許你嘲笑的PanelManager行爲和測試實際行爲Controller迴應PanelManager的嘲弄行爲。

+0

謝謝我剛剛看到您的回覆。那麼爲什麼會這樣工作?因爲我沒有使用'doCallRealMethod()',它沒有關係? – Lazaro

+0

@拉齊羅你問「爲什麼會這樣?」我不確定那個「那」是指什麼。在我回答這個部分:「使用PowerMockRunner而不是MockitoJUnitRuner」修復了ClassNotPreparedException。我的答案中的其他建議避免了完全使用「PowerMockito.doCallRealMethod()」,而是使用真正的Controller實例。 – glytching