如何通过 Spring MockMvc 将日期对象作为请求参数传递
How to pass date objects as request parameters through Spring MockMvc
我有一个使用 Spring 的 MockMvc 测试框架来命中 REST 端点的单元测试。其余端点需要发送两个字符串路径变量,以及两个作为 @RequestParameters 传递的 java.util.Date
对象。当我 运行 测试时,它失败了,因为 Date 对象不存在,或者无法从字符串 JSON 表示形式序列化为 Date 对象。作为记录,在到达 .perform()
中列出的终点之前执行失败,所以这个问题不是来自被测试的代码。它来自测试。
这是我的测试:
@Test
public void testGetHitsForCell() {
String categoryName = "categoryName";
try {
String startDateJson = gson.toJson(new Date());
String endDateJson = gson.toJson(new Date());
ResultActions ra = mvc.perform(MockMvcRequestBuilders.get("/rest/tickets/" + ticketName + "/" + categoryName).requestAttr("startDate", new Date())
.requestAttr("endDate", new Date()).with(user(user)));
MvcResult aResult = ra.andReturn();
MockHttpServletResponse response = aResult.getResponse();
assertTrue(response.getContentType().equals("application/json;charset=UTF-8"));
assertTrue(gson.fromJson(response.getContentAsString(), PaginatedResults.class) instanceof PaginatedResults);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
端点如下所示:
/rest/ticket/{ticketName}/{categoryName}?startDate=2015-07-21T14%3A26%3A51.972-0400&endDate=2015-08-04T14%3A26%3A51.972-0400
这是 MockMvc 抛出的异常:
org.springframework.web.bind.MissingServletRequestParameterException: Required Date parameter 'startDate' is not present
我的测试应用程序上下文如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<import resource="classpath:propertiesPlaceholder.xml" />
<import resource="classpath:cache.xml" />
<import resource="classpath:mongo-context.xml" />
<import resource="classpath:securityContext.xml" />
<import resource="classpath:service-commons.xml" />
<import resource="classpath:mockUserProviderContext.xml" />
<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- Use the Jackson mapper defined above to serialize dates appropriately -->
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<mvc:default-servlet-handler/>
<!-- Jackson Mapper -->
<bean name="jacksonObjectMapper"
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="featuresToDisable">
<array>
<util:constant
static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS" />
<util:constant
static-field="com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS" />
</array>
</property>
</bean>
<!-- SimpleDateFormat for Jackson to use for formatting Date objects -->
<bean id="standardDateFormat" class="java.text.SimpleDateFormat">
<constructor-arg index="0" value="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" />
</bean>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<context:component-scan base-package="ticketApp" />
<context:component-scan base-package="mongodb.dao.TicketDao" />
<context:component-scan base-package="service.commons.*" />
</beans>
我该怎么做才能将这些 Date 对象正确传递到上述 rest 端点?
事实证明这里有几处错误:
我不需要对日期对象使用 .requestAttr() 调用。我只是将日期的字符串表示作为查询参数添加到调用中,如下所示:
private String end = "2015-12-31T23:59:59.999Z";
private String start = "2012-01-01T00:00:00.000Z";
ResultActions ra = mvc.perform(MockMvcRequestBuilders.get("/rest/hits/" + modelId + "/0" + "?startDate=" + start + "&endDate=" + end).with(user(user)));
另外,传入 Date 对象导致了一个问题,因为它们的字符串表示格式是错误的。菜鸟错误。
我知道现在回答已经来不及了,但只是为了将来有人搜索。
为了解决这个问题你可以使用get(URL).param
代替:
mvc.perform(MockMvcRequestBuilders.get("/rest/tickets/" + ticketName + "/" + categoryName).param("startDate", new Date())
.param("endDate", new Date()).with(user(user)));
看来MockMVC是傻了。
这行不通
this.mockMvc.perform(get()
.queryParam("startDate","2011-01-01")
.queryParam("endDate", "2000-11-31")
您必须直接在 URL 中硬编码日期,如下所示:
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = get(CONFIRMATION_API_GET+"?startDate=2019-09-12&endDate=2019-10-13");
我有一个使用 Spring 的 MockMvc 测试框架来命中 REST 端点的单元测试。其余端点需要发送两个字符串路径变量,以及两个作为 @RequestParameters 传递的 java.util.Date
对象。当我 运行 测试时,它失败了,因为 Date 对象不存在,或者无法从字符串 JSON 表示形式序列化为 Date 对象。作为记录,在到达 .perform()
中列出的终点之前执行失败,所以这个问题不是来自被测试的代码。它来自测试。
这是我的测试:
@Test
public void testGetHitsForCell() {
String categoryName = "categoryName";
try {
String startDateJson = gson.toJson(new Date());
String endDateJson = gson.toJson(new Date());
ResultActions ra = mvc.perform(MockMvcRequestBuilders.get("/rest/tickets/" + ticketName + "/" + categoryName).requestAttr("startDate", new Date())
.requestAttr("endDate", new Date()).with(user(user)));
MvcResult aResult = ra.andReturn();
MockHttpServletResponse response = aResult.getResponse();
assertTrue(response.getContentType().equals("application/json;charset=UTF-8"));
assertTrue(gson.fromJson(response.getContentAsString(), PaginatedResults.class) instanceof PaginatedResults);
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
端点如下所示:
/rest/ticket/{ticketName}/{categoryName}?startDate=2015-07-21T14%3A26%3A51.972-0400&endDate=2015-08-04T14%3A26%3A51.972-0400
这是 MockMvc 抛出的异常:
org.springframework.web.bind.MissingServletRequestParameterException: Required Date parameter 'startDate' is not present
我的测试应用程序上下文如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<import resource="classpath:propertiesPlaceholder.xml" />
<import resource="classpath:cache.xml" />
<import resource="classpath:mongo-context.xml" />
<import resource="classpath:securityContext.xml" />
<import resource="classpath:service-commons.xml" />
<import resource="classpath:mockUserProviderContext.xml" />
<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- Use the Jackson mapper defined above to serialize dates appropriately -->
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<mvc:default-servlet-handler/>
<!-- Jackson Mapper -->
<bean name="jacksonObjectMapper"
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="featuresToDisable">
<array>
<util:constant
static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS" />
<util:constant
static-field="com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS" />
</array>
</property>
</bean>
<!-- SimpleDateFormat for Jackson to use for formatting Date objects -->
<bean id="standardDateFormat" class="java.text.SimpleDateFormat">
<constructor-arg index="0" value="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" />
</bean>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<context:component-scan base-package="ticketApp" />
<context:component-scan base-package="mongodb.dao.TicketDao" />
<context:component-scan base-package="service.commons.*" />
</beans>
我该怎么做才能将这些 Date 对象正确传递到上述 rest 端点?
事实证明这里有几处错误:
我不需要对日期对象使用 .requestAttr() 调用。我只是将日期的字符串表示作为查询参数添加到调用中,如下所示:
private String end = "2015-12-31T23:59:59.999Z";
private String start = "2012-01-01T00:00:00.000Z";
ResultActions ra = mvc.perform(MockMvcRequestBuilders.get("/rest/hits/" + modelId + "/0" + "?startDate=" + start + "&endDate=" + end).with(user(user)));
另外,传入 Date 对象导致了一个问题,因为它们的字符串表示格式是错误的。菜鸟错误。
我知道现在回答已经来不及了,但只是为了将来有人搜索。
为了解决这个问题你可以使用get(URL).param
代替:
mvc.perform(MockMvcRequestBuilders.get("/rest/tickets/" + ticketName + "/" + categoryName).param("startDate", new Date())
.param("endDate", new Date()).with(user(user)));
看来MockMVC是傻了。 这行不通
this.mockMvc.perform(get()
.queryParam("startDate","2011-01-01")
.queryParam("endDate", "2000-11-31")
您必须直接在 URL 中硬编码日期,如下所示:
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = get(CONFIRMATION_API_GET+"?startDate=2019-09-12&endDate=2019-10-13");