使用EasyMock和jmock模拟

来源:互联网

今日做单元测试遇到一个问题。在java web application程序里面有一个函数doGet(HttpServletRequest request, HttpServletResponse response),要给它做单元测试,首先想到的就是mock出request和response,这不麻烦,但是该函数代码里面出现了Manifest mainfest = new Manifest(getServletContext().getResourceAsStream(MANIFEST_PATH));这样的句子,于是不得不还要mock出ServletContext。受益于http://www.liaoxuefeng.com/archives/52这篇文章,我找到了解决方法。

仍然采用网上的一个例子:

一个用户验证的LoginServlet类:

package mock.test;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginServlet extends HttpServlet{
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
if ("admin".equals(username) && "123456".equals(password)) {
ServletContext context = getServletContext();
RequestDispatcher dispatcher = context
.getNamedDispatcher("dispatcher");
dispatcher.forward(request, response);
} else {
throw new RuntimeException("Login failed.");
}
}
}

这个Servlet实现简单的用户验证的功能,若用户名和口令匹配“admin”和“123456”,则请求被转发到指定的dispatcher上,否则,直接抛出RuntimeException。

为了测试doPost()方法,我们需要模拟HttpServletRequest,ServletContext和RequestDispatcher 对象,以便脱离J2EE容器来测试这个Servlet。首先用EasyMock实验,采用easymock3.0.jar

package mock.test;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.easymock.EasyMock;
import org.easymock.IMocksControl;

import junit.framework.TestCase;
public class LoginServletTest2 extends TestCase{
public void testLoginFailed() throws Exception {
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getParameter("username")).andReturn("admin");
EasyMock.expect(request.getParameter("password")).andReturn("1234").once();
EasyMock.replay(request);
LoginServlet servlet = new LoginServlet();
try {
servlet.doPost(request, null);
fail("Not caught exception!");
} catch (RuntimeException re) {
assertEquals("Login failed.", re.getMessage());
}
EasyMock.verify(request);
}

public void testLoginOK() throws Exception {
IMocksControl control = EasyMock.createControl();
HttpServletRequest requestObj = control.createMock(HttpServletRequest.class);
final ServletContext contextObj = control.createMock(ServletContext.class);
RequestDispatcher dispatcherObj= control.createMock(RequestDispatcher.class);

EasyMock.expect(requestObj.getParameter("username")).andReturn("admin").once();
EasyMock.expect(requestObj.getParameter("password")).andReturn("123456").once();

EasyMock.expect(contextObj.getNamedDispatcher("dispatcher")).andReturn(dispatcherObj).once();
dispatcherObj.forward(requestObj, null);
EasyMock.expectLastCall().once();

EasyMock.replay(control);

LoginServlet servlet = new LoginServlet() {
public ServletContext getServletContext() {
return contextObj;
}
};
servlet.doPost(requestObj, null);
EasyMock.verify(control);
}
}

这里需要注意的是,为了让getServletContext()方法返回我们创建的ServletContext Mock对象,我们定义一个匿名类并覆写getServletContext()方法。

下面用jmock实验一下,需要jmock-junit3-2.5.1.jar,jmock-2.5.1.jar

package mock.test;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit3.MockObjectTestCase;
public class LoginServletTest extends MockObjectTestCase{
public void testLoginFailed() throws Exception {
Mockery context = new Mockery();
final HttpServletRequest mockRequest = context.mock(HttpServletRequest.class);
context.checking(new Expectations() {
{
one(mockRequest).getParameter("username");
will(returnValue("admin"));

one(mockRequest).getParameter("password");
will(returnValue("12345"));
}
});
LoginServlet servlet = new LoginServlet();
try {
servlet.doPost(mockRequest, null);
fail("Not caught exception!");
} catch (RuntimeException re) {
assertEquals("Login failed.", re.getMessage());
}
}

public void testLoginOK() throws Exception {
Mockery context = new Mockery();
final HttpServletRequest mockRequest = context.mock(HttpServletRequest.class);
final HttpServletResponse mockResponse = context.mock(HttpServletResponse.class);
final ServletContext mockContext = context.mock(ServletContext.class);
final RequestDispatcher mockDispatcher = context.mock(RequestDispatcher.class);
LoginServlet servlet = new LoginServlet() {
public ServletContext getServletContext() {
return mockContext;
}
};
context.checking(new Expectations() {
{
one(mockRequest).getParameter("username");
will(returnValue("admin"));

one(mockRequest).getParameter("password");
will(returnValue("123456"));

one(mockContext).getNamedDispatcher("dispatcher");
will(returnValue(mockDispatcher));
one (mockDispatcher).forward(mockRequest, null);
}
});
servlet.doPost(mockRequest, null);
}
}

原文:http://blog.sina.com.cn/s/blog_69d9bff30100yd11.html

发表评论