Java 如何模拟 servletContext 而不是 Servlet 或 HttpServletRequest?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22610503/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to mock a servletContext instead of Servlet or HttpServletRequest?
提问by Vivek
I have an independent project for writing test cases; the problem is I can't mock HttpServletRequest
, simply because in my servlet there are calls like getServletContext()
as test cases are running from the outside servlet container. It will always return an error saying "no context found". This is just one dependency with the servlet container; there can be hundreds. For example, initialContext.lookup()
also depends on a container.
我有一个独立的编写测试用例的项目;问题是我不能模拟HttpServletRequest
,只是因为在我的 servlet 中有一些调用,就像getServletContext()
测试用例从外部 servlet 容器运行一样。它总是会返回一个错误,说“没有找到上下文”。这只是 servlet 容器的一个依赖项;可能有数百个。例如,initialContext.lookup()
还取决于容器。
How can I use Mockito to write a test case in this scenario? Please don't ask for an error message; it's more of a logical problem than technical.
在这种情况下如何使用 Mockito 编写测试用例?请不要询问错误信息;这更像是一个逻辑问题而不是技术问题。
Looking on the internet for tutorials makes me wonder if I am doing something seriously wrong. No one seems to have encountered this problem before... How can you mock HttpServletRequest
without ever having getServletContext()
called in the servlet? I mean seriously, how rare can it be?
在互联网上寻找教程让我怀疑我是否做错了什么。以前似乎没有人遇到过这个问题......你怎么能在HttpServletRequest
没有getServletContext()
调用 servlet 的情况下模拟?我的意思是说真的,它有多罕见?
采纳答案by René Link
You have a servlet implementation that uses the ServletContext
, e.g.
您有一个使用 servlet 实现ServletContext
,例如
public class SomeServlet extends HttpServlet{
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
Object attribute = servletContext.getAttribute("test");
System.out.println(attribute.toString());
}
}
in this case you have 2 options to test the doGet
method
在这种情况下,您有 2 个选项来测试该doGet
方法
Use powermock's partitial mockingto only mock the getServletContext
method.
使用 powermock 的部分模拟只模拟getServletContext
方法。
@RunWith(PowerMockRunner.class)
public class SomeServletTest {
@Test
public void onGet() throws ServletException, IOException{
SomeServlet someServlet = PowerMock.createPartialMock(SomeServlet.class, "getServletContext");
ServletContext servletContext = PowerMock.createNiceMock(ServletContext.class);
HttpServletRequest httpServletRequest = PowerMock.createNiceMock(HttpServletRequest.class);
HttpServletResponse httpServletResponse = PowerMock.createNiceMock(HttpServletResponse.class);
someServlet.getServletContext();
PowerMock.expectLastCall().andReturn(servletContext);
servletContext.getAttribute("test");
PowerMock.expectLastCall().andReturn("hello");
PowerMock.replay(someServlet, servletContext, httpServletRequest, httpServletResponse);
someServlet.doGet(httpServletRequest, httpServletResponse);
}
}
or a simpler way is to just override the getServletContext
method. In this case you don't need powermock. You can just do it using easymock. e.g.
或者更简单的方法是覆盖该getServletContext
方法。在这种情况下,您不需要 powermock。你可以使用easymock来做到这一点。例如
public class SomeServletTest {
@Test
public void onGet() throws ServletException, IOException{
HttpServletRequest httpServletRequest = EasyMock.createNiceMock(HttpServletRequest.class);
HttpServletResponse httpServletResponse = EasyMock.createNiceMock(HttpServletResponse.class);
final ServletContext servletContext = EasyMock.createNiceMock(ServletContext.class);
SomeServlet someServlet = new SomeServlet(){
public ServletContext getServletContext() {
return servletContext; // return the mock
}
};
EasyMock.expect(servletContext.getAttribute("test")).andReturn("hello");
EasyMock.replay(servletContext, httpServletRequest, httpServletResponse);
someServlet.doGet(httpServletRequest, httpServletResponse);
}
}
there can be 100's. like initialContext.lookup() also dependent on container.
可以有 100 个。像 initialContext.lookup() 也依赖于容器。
In this case you can either create an InitialContext
mock and use this.
If your code creates a new InitialContext
, e.g.
在这种情况下,您可以创建一个InitialContext
模拟并使用它。如果您的代码创建了一个新的InitialContext
,例如
public void someMethod(){
InitialContext context = new InitialContext();
context.lookup(....);
}
you can simply extract the InitialContext
instantiation to a protected method that you can override in your tests like I showed above with the ServletContext
您可以简单地将InitialContext
实例化提取到一个受保护的方法中,您可以在测试中覆盖该方法,就像我上面用ServletContext
public void someMethod(){
InitialContext context = createInitialContext();
context.lookup(....);
}
protected InitialContext createInitialContext(){
return new InitialContext(); // can be overridden by a subclass
// and therefore by tests as well to
// return a mock
}
If you don't want or you can't modify the code in this way, then you can use Powermock
to intercept the constructor.
如果你不想或者不能用这种方式修改代码,那么你可以使用Powermock
到拦截构造函数。
EDIT
编辑
Can you post your Mockito code? It would be a pleasure, since the methods are named differently.
你能发布你的 Mockito 代码吗?这将是一种乐趣,因为这些方法的名称不同。
@Test
public void onGet() throws ServletException, IOException {
HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class);
HttpServletResponse httpServletResponse = Mockito.mock(HttpServletResponse.class);
final ServletContext servletContext = Mockito.mock(ServletContext.class);
SomeServlet someServlet = new SomeServlet(){
public ServletContext getServletContext() {
return servletContext; // return the mock
}
};
Mockito.doReturn("hello").when(servletContext).getAttribute("test");
someServlet.doGet(httpServletRequest, httpServletResponse);
}