Spring REST控制器的单元测试'位置'标题
问题描述:
在Spring REST控制器中创建资源后,我将返回它在标题中的位置,如下所示。Spring REST控制器的单元测试'位置'标题
@RequestMapping(..., method = RequestMethod.POST)
public ResponseEntity<Void> createResource(..., UriComponentsBuilder ucb) {
...
URI locationUri = ucb.path("/the/resources/")
.path(someId)
.build()
.toUri();
return ResponseEntity.created(locationUri).build();
}
在单元测试中,我正在检查它的位置,如下所示。
@Test
public void testCreateResource(...) {
...
MockHttpServletRequestBuilder request = post("...")
.content(...)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON);
request.session(sessionMocked);
mvc.perform(request)
.andExpect(status().isCreated())
.andExpect(header().string("Location", "/the/resources" + id);
}
此结果案例失败并显示以下消息。
java.lang.AssertionError: Response header Location expected:</the/resources/123456> but was:<http://localhost/the/resources/123456>
好像我必须为期望的位置标题提供上下文前缀http://localhost
。
- 硬编码上下文安全吗?如果是这样,为什么?
- 如果不是,那么正确地为测试用例生成正确的方法是什么?
答
如果您不需要在响应的Location标头中有一个完整的URI(即没有要求,设计约束等):考虑切换到使用相对URI(从HTTP标准角度来看这是有效的 - 请参阅[1]:https://tools.ietf.org/html/rfc7231)相对URI是现代浏览器和库支持的建议标准。这将允许您测试端点的行为,并使其从长远来看不那么脆弱。
如果您需要断言的完整路径,因为你正在使用MockMvc,你可以在测试请求设置URI到你想要什么:
@Autowired
private WebApplicationContext webApplicationContext;
@Test
public void testCreateResource() {
MockMvc mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
mvc.perform(MockMvcRequestBuilders.get(new URI("http://testserver/the/resources")));
这将使注入建设者产生“http://testserver “当构建被调用时。请注意,未来的框架更改可能会导致您头痛,如果他们删除此测试行为。
答
我在猜测,因为您使用UriComponentsBuilder
来建立您的URI它设置您的位置标题中的主机名。如果你使用的只是new URI("/the/resources")
之类的东西,你的测试已经过去了。
在你的情况,我会使用redirectedUrlPattern匹配重定向URL:
.andExpect(redirectedUrlPattern("http://*/the/resources"))
这将匹配任何主机名,所以你不必硬编码本地主机。详细了解您可以与AntPathMatcher
here一起使用的不同模式。
您的解决方案测试重定向行为。 OP想要测试位置标头。 我必须承认,直到今天我都不知道“redirectedUrlPattern” –