我正在測試使用EasyMock對象的HttpServletRequest
和HttpServletResponse
參數的servlet的doPost()
方法。在doPost()
方法中,我正在測試請求,並且響應對象用作另一個類的靜態方法類的參數,並且我想忽略(即不按預期記錄)在此方法內對請求和響應對象所做的任何調用呼叫(無論如何,這與測試無關)。例如servlet類的doPost()
方法我測試看起來像這樣:如何關閉EasyMock對象的錄製?
@Override
protected void doPost(final HttpServletRequest servletRequest,
final HttpServletResponse servletResponse)
throws ServletException, IOException
{
// handle an "updateFolder" event
String eventParameter = servletRequest.getParameter("event");
if ("updateFolder".equalsIgnoreCase(eventParameter))
{
// update the news documents folder settings
String folderId = servletRequest.getParameter("folderId");
IPortletContext portletContext = PortletContextFactory.createPortletContext(servletRequest, servletResponse);
IPortletResponse portletResponse = portletContext.getResponse();
portletResponse.setSettingValue(SettingType.CommunityPortlet, "NEWS_DOCUMENTS_FOLDER_ID", folderId);
}
// redirect to the appropriate URL
servletResponse.sendRedirect(redirectUrl);
}
當上面的代碼獲取步驟,其中PortletContextFactory.createPortletContext()
叫我真的不關心什麼方法調用上的要求而作出以及該方法中的響應對象,但是如果在測試此方法時傳遞模擬請求和響應對象,則EasyMock會收到錯誤,告訴我缺少行爲定義。比如我有一個測試方法,看起來像這樣:
@Test
public void testPostWithUpdate()
throws Exception
{
// create mock objects and record their expected calls
HttpServletRequest mockServletRequest = createMock(HttpServletRequest.class);
HttpServletResponse mockServletResponse = createMock(HttpServletResponse.class);
IPortletResponse mockPortletResponse = createMock(IPortletResponse.class);
IPortletContext mockPortletContext = createMock(IPortletContext.class);
expect(mockServletRequest.getContextPath()).andReturn(null);
expect(mockServletRequest.getParameter("event")).andReturn("updateFolder");
expect(mockServletRequest.getParameter("folderId")).andReturn(null);
expect(PortletContextFactory.createPortletContext(mockServletRequest, mockServletResponse)).andReturn(mockPortletContext);
expect(mockPortletContext.getResponse()).andReturn(mockPortletResponse);
mockPortletResponse.setSettingValue(SettingType.CommunityPortlet, "NEWS_DOCUMENTS_FOLDER_ID", null);
mockServletResponse.sendRedirect(EasyMock.anyObject(String.class));
// take the mock objects out of record state
replay(mockPortletContext, mockPortletResponse, mockServletRequest, mockServletResponse);
// instantiate an object of the class and run the method we want to test
ControllerServlet controllerServlet = new ControllerServlet();
controllerServlet.doPost(mockServletRequest, mockServletResponse);
// verify that our mocks behaved as expected
verify(mockPortletContext, mockPortletResponse, mockServletRequest, mockServletResponse);
}
我收到以下錯誤,當我運行測試類:
com.plumtree.openfoundation.util.XPIllegalStateException: missing behavior definition for the preceding method call getCharacterEncoding()
at com.plumtree.openfoundation.util.XPException.GetInstance(XPException.java:397)
at com.plumtree.openfoundation.util.XPException.GetInstance(XPException.java:350)
at com.plumtree.openfoundation.web.XPRequest.InitRequest(XPRequest.java:201)
at com.plumtree.openfoundation.web.XPRequest.<init>(XPRequest.java:111)
at com.plumtree.remote.portlet.PortletContextFactory.createPortletContext(PortletContextFactory.java:32)
at com.abc.servlet.ControllerServletTest.testPostWithUpdate(ControllerServletTest.java:31)
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.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
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)
Caused by: java.lang.IllegalStateException: missing behavior definition for the preceding method call getCharacterEncoding()
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:43)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:73)
at $Proxy4.setCharacterEncoding(Unknown Source)
at com.plumtree.openfoundation.web.XPRequest.InitRequest(XPRequest.java:135)
... 25 more
我假設的錯誤以上均爲不記錄引起的方法調用在PortletContextFactory.createPortletContext()
方法中對模擬請求和響應對象作爲參數傳入。如果實際上這裏發生了什麼,那麼我該如何重新修改事件,以便對請求進行的方法調用和PortletContextFactory.createPortletContext()
方法的響應模擬都被忽略了?
EasyMock也沒有,它有_nice mocks_。易用性在很大程度上是個人品味和體驗的問題。 – 2010-09-17 21:55:01
@彼得我與他們合作過,現在我更喜歡Mockito。這可能是一個味道的問題,仍然恕我直言Mockito有一個整潔的API。換句話說,Mockito是一個很好的模擬;) – 2010-09-18 12:27:58