Java 用url字符串创建模拟HttpServletRequest?
我有一个服务在HttpServletRequest对象上执行一些工作,特别是使用request.getParameterMap和request.getParameter来构造一个对象 我想知道是否有一种简单的方法可以获取提供的url,比如字符串形式Java 用url字符串创建模拟HttpServletRequest?,java,mocking,servlets,Java,Mocking,Servlets,我有一个服务在HttpServletRequest对象上执行一些工作,特别是使用request.getParameterMap和request.getParameter来构造一个对象 我想知道是否有一种简单的方法可以获取提供的url,比如字符串形式 String url = "http://www.example.com/?param1=value1¶m"; 并轻松地将其转换为HttpServletRequest对象,以便使用单元测试对其进行测试?或者至少让request.ge
String url = "http://www.example.com/?param1=value1¶m";
并轻松地将其转换为HttpServletRequest对象,以便使用单元测试对其进行测试?或者至少让request.getParameterMap和request.getParameter正常工作?Spring的Spring测试模块中有
如果您使用的是maven,则可能需要将适当的依赖项添加到pom.xml。您可以在找到SpringTest。您通常会在集成测试中测试这些类型的东西,它实际上连接到一个服务。要进行单元测试,您应该测试servlet的doGet/doPost方法使用的对象
一般来说,您不希望servlet方法中有太多代码,您希望创建一个bean类来处理操作,并将您自己的对象传递给它,而不是servlet API对象。模拟
HttpServletRequest的最简单方法是:
创建一个匿名子类:
HttpServletRequest mock = new HttpServletRequest ()
{
private final Map<String, String[]> params = /* whatever */
public Map<String, String[]> getParameterMap()
{
return params;
}
public String getParameter(String name)
{
String[] matches = params.get(name);
if (matches == null || matches.length == 0) return null;
return matches[0];
}
// TODO *many* methods to implement here
};
使用HttpUnit,不要模仿请求
下面介绍如何使用MockHttpServletRequest:
// given
MockHttpServletRequest request = new MockHttpServletRequest();
request.setServerName("www.example.com");
request.setRequestURI("/foo");
request.setQueryString("param1=value1¶m");
// when
String url = request.getRequestURL() + '?' + request.getQueryString(); // assuming there is always queryString.
// then
assertThat(url, is("http://www.example.com:80/foo?param1=value1¶m"));
对于那些想用Json有效负载模拟POST
HttpServletRequest的人来说,下面是Kotlin中的内容,但这里的关键是当你想模拟请求时的。从HttpServletRequest
@Mock
private lateinit var request: HttpServletRequest
@Mock
private lateinit var response: HttpServletResponse
@Mock
private lateinit var chain: FilterChain
@InjectMocks
private lateinit var filter: ValidationFilter
@Test
fun `continue filter chain with valid json payload`() {
val payload = """{
"firstName":"aB",
"middleName":"asdadsa",
"lastName":"asdsada",
"dob":null,
"gender":"male"
}""".trimMargin()
whenever(request.requestURL).
thenReturn(StringBuffer("/profile/personal-details"))
whenever(request.method).
thenReturn("PUT")
whenever(request.inputStream).
thenReturn(DelegatingServletInputStream(ByteArrayInputStream(payload.toByteArray())))
filter.doFilter(request, response, chain)
verify(chain).doFilter(request, response)
}
再说一次,为什么仅仅因为方法采用了某种类型的参数作为输入,就错过了增加测试覆盖率(即代码健壮性)的机会?这取决于,您是在尝试对servlet API进行单元测试,还是在尝试对自己的代码进行单元测试?“一般而言”您不希望在servlet方法中包含任何代码。实际上,你永远都会。您将拥有帮助器类、实用程序方法、解析、验证、模型转换,有时甚至还有业务逻辑(可怕!)。既然您这样做了,您就需要对它们进行单元测试。因此,您需要模拟servlet请求来创建定义良好的测试场景。模拟ServletAPI与测试它恰恰相反。它将从测试用例中完全删除它。使用这个MockHttpServletRequest实际上完成了这项工作,因为我只需要一个功能完整的HttpServletRequest注意,当设置queryString时,参数映射不会在MockHttpServletRequest中自动更新。因此,如果在代码中使用request.getParameter(),则必须先在测试设置中显式设置它,即使它一开始看起来可能是多余的。我注意到了同样的情况。查询字符串和参数似乎不同步upjee api jar 6或8将需要进行此操作。注释中的内容是什么?
@Mock
private lateinit var request: HttpServletRequest
@Mock
private lateinit var response: HttpServletResponse
@Mock
private lateinit var chain: FilterChain
@InjectMocks
private lateinit var filter: ValidationFilter
@Test
fun `continue filter chain with valid json payload`() {
val payload = """{
"firstName":"aB",
"middleName":"asdadsa",
"lastName":"asdsada",
"dob":null,
"gender":"male"
}""".trimMargin()
whenever(request.requestURL).
thenReturn(StringBuffer("/profile/personal-details"))
whenever(request.method).
thenReturn("PUT")
whenever(request.inputStream).
thenReturn(DelegatingServletInputStream(ByteArrayInputStream(payload.toByteArray())))
filter.doFilter(request, response, chain)
verify(chain).doFilter(request, response)
}