在SpringRESTController中创建一个资源后,我将返回它在头中的位置,如下所示。
@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
。
- 硬编码上下文安全吗?如果安全,为什么?
- 如果没有,正确生成测试用例的正确方法是什么?
3条答案
按热度按时间9udxz4iz1#
我猜是因为你使用
UriComponentsBuilder
来构建你的URI,所以它在你的位置头中设置了主机名,如果你只使用new URI("/the/resources")
这样的东西,你的测试就会通过。在您的情况下,我会使用redirectedUrlPattern来匹配重定向URL:
.andExpect(redirectedUrlPattern("http://*/the/resources"))
这将匹配任何主机名,因此您不必硬编码 localhost。了解更多关于可用于
AntPathMatcher
here的不同模式的信息。ylamdve62#
如果您不需要在响应的Location标头中包含完整的URI(即无要求、设计约束等):考虑切换到使用相对URI(从HTTP标准的Angular 来看是有效的-参见[1]:https://www.rfc-editor.org/rfc/rfc7231)Relative URI是一个被提议的标准,它被现代浏览器和库所支持,这将允许您测试端点的行为,并使其在长期运行中不那么脆弱。
如果您需要Assert完整路径,因为您使用的是MockMvc,您可以将测试请求中的uri设置为您想要的值:
这将使注入的构建器在调用构建时产生“http://testserver”。注意,如果将来的框架更改删除了此测试行为,可能会让您头疼。
igsr9ssn3#
面对同样的问题,我尝试了 Suraj Bajaj 提供的解决方案,对我来说效果很好。
然后我尝试直接Assert头字段“Location”的文本,最后使用了containsString()。
这个简单的解决方案也应该是一个可行的替代方案,只要服务器上下文和相对/绝对路径的问题不重要: