我正在尝试使用TestRestTemplate创建一个Spring Boot控制器的测试。要求仅将控制器绝对需要的内容包括在测试上下文中,因此,将测试的整个应用程序上下文细化是不可行的。
当前,由于端点返回404,因此测试失败。该端点在生产中正常工作。似乎该控制器未在Web Servlet中注册。
控制器显示如下:
@RestController
class MyController {
@GetMapping("/endpoint")
fun endpoint(): ResponseDto {
return ResponseDto(data = "Some data")
}
}
data class ResponseDto(val data: String)
测试如下:
@SpringBootTest(
classes = [MyController::class, ServletWebServerFactoryAutoConfiguration::class],
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
internal class MyControllerTestRestTemplateTest(
@Autowired private val restTemplate: TestRestTemplate
) {
@Test
fun `should work`() {
val result = restTemplate.getForEntity("/endpoint", String::class.java)
result.body.shouldMatchJson(
"""
{
"data": "Some data"
}
""")
}
}
如何使此测试设置正常工作?
答案 0 :(得分:0)
要求仅将控制器绝对需要的内容包括在测试上下文中,...
SpringBoot已经为此提供了工具-请参见@WebMvcTest
slice documentation或this SO answer。
答案 1 :(得分:0)
根据您的要求:
要求仅对 控制器包含在测试环境中,因此将整个 测试的应用程序上下文不是一个选择。
您应该考虑使用@WebMvcTest
仅测试Web层。使用当前的@SpringBootTest
和随机端口,您将引导整个Spring Context并启动嵌入式Tomcat。使用@WebMvcTest
,您可以插入MockMvc
实例,并在响应正文/标头/状态上声明内容。
一个Java示例可能看起来像这样
@WebMvcTest(MyController.class)
class MyControllerTests {
@Autowired
private MockMvc mvc;
@Test
void testExample() throws Exception {
this.mvc.perform(get("/endpoint")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string("YOUR_STRING_HERE"));
}
}
一个有效的Kotlin示例如下所示
@WebMvcTest(MyController::class)
internal class MyControllerTests(@Autowired private val mockMvc: MockMvc) {
@Test
fun testExample() {
this.mockMvc.perform(MockMvcRequestBuilders.get("/endpoint")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk)
.andExpect(content().json("""
{
"data": "Some data"
}
""".trimIndent()))
}
}
答案 2 :(得分:0)
rieckpil和Josef的答案都是正确的,我同意使用@WebMvcTest是更好的方法。
如果您坚持继续使用@SpringBootTest和TestRestTemplate:您正在使用webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT。这意味着您的TestRestTemplate不知道要使用哪个端口。您需要在字符串
中包括整个URL,包括应用程序正在运行的端口。通过添加
@LocalServerPort
int randomServerPort = 0
然后提供完整的网址
val result = restTemplate.getForEntity("http://localhost:${randomServerPort}/endpoint", String::class.java)