使用 servlet 和会话进行测试时获取 MissingMethodInvocationException

Posted

技术标签:

【中文标题】使用 servlet 和会话进行测试时获取 MissingMethodInvocationException【英文标题】:Getting MissingMethodInvocationException while testing with servlet and session 【发布时间】:2022-01-21 21:59:13 【问题描述】:

我正在尝试测试我的 servlet,看看它是否使用会话中传递的一些参数调用我的 DAOService,但遇到了这个问题

日志:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);
at Servlet.SupplierServletTest.supplierServlet_StandardTest(SupplierServletTest.java:32)

代码

SupplierServlet supplierServlet = new SupplierServlet();
MockHttpServletRequest request = new MockMvcRequestBuilders.get("/SupplierServlet").buildRequest(new MockServletContext());
MockHttpServletResponse response = new MockHttpServletResponse();
MockHttpSession session = new MockHttpSession();

when(request.getSession()).thenReturn(session); //This is the line 32 that the log mentioned, I deleted the session part and the problem was the same for the following lines
when(request.getParameter("Name")).thenReturn("test"); 
when(request.getParameter("Address")).thenReturn("test");
when(request.getParameter("Phone")).thenReturn("1234");

supplierServlet.processRequest(request, response);
supplierDAO = mock(SupplierDAO.class);
verify(supplierDAO).newSupplier(new Supplier("test", "test", "1234"));

感谢任何提示

【问题讨论】:

MockHttpServletRequest 不是 Mockito 识别的模拟。 我正在使用 Spring 测试中的模拟,正如我在上一个问题中所建议的那样。我现在正在尝试按照 Mockito 的方式做事,看看是否有任何改进,但到目前为止的启动很痛苦 只需使用addParameter()javadoc(独家!)或使用Mockio... 【参考方案1】:

至于初始化MockHttpServletRequest,你应该使用Spring提供的构建器。由于它是 Spring 框架提供的一个类(并且不是 Mockito 模拟),使用 Mockito 模拟其方法会导致错误。

MockHttpServletResponse response = new MockHttpServletResponse();
MockHttpSession session = new MockHttpSession();
MockHttpServletRequest request = MockMvcRequestBuilders.get("/SupplierServlet")
    .session(session)
    .param("Name", "test")
    .param("Address", "test")
    .param("Phone", "1234")
    .buildRequest(new MockServletContext());

supplierServlet.processRequest(request, response);
supplierDAO = mock(SupplierDAO.class);
verify(supplierDAO).newSupplier(new Supplier("test", "test", "1234"));

此外,您的 supplierDAO 模拟毫无用处。模拟一个对象后,您需要将其注入到被测代码中。它通常通过将模拟作为函数参数传递来完成。而在您的测试中,您正在尝试验证从未使用过的模拟上的调用。

【讨论】:

谢谢,supplierDAO 部分用于验证是否调用它,因为如果 servlet 在测试中按预期工作,则应该调用它 @LongDoan 是的,但是您的测试代码中的SupplierDAO(模拟)实例独立于您的servlet 中的SupplierDAO 实例。除非您的 servlet 也使用相同的实例,否则您无法验证对(模拟)实例的调用。 我明白了,谢谢

以上是关于使用 servlet 和会话进行测试时获取 MissingMethodInvocationException的主要内容,如果未能解决你的问题,请参考以下文章

会话丢失并在每个 servlet 请求中创建为新的

7 Servlet 会话技术

如何有效地破坏 Java Servlet 中的“会话”?

会话技术cookie和session详解

[javaEE] Servlet中Session的使用

Servlet 和 JSP 中的会话管理 [重复]