运行 Spring Boot MockMvc 测试时“找不到返回值的转换器”
Posted
技术标签:
【中文标题】运行 Spring Boot MockMvc 测试时“找不到返回值的转换器”【英文标题】:"No converter found for return value" when running Spring Boot MockMvc test 【发布时间】:2020-06-15 19:37:33 【问题描述】:我正在尝试创建一个 Spring Boot 控制器的 MockMvc 测试。我特别不希望整个应用程序上下文被启动,所以我将上下文限制为有问题的控制器。但是,测试失败并返回 500 并输出以下日志:
2020-03-03 13:04:06.904 WARN 8207 --- [ main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class main.endpoints.ResponseDto]
Spring Boot 上下文似乎不知道如何找到 Jackson。
这里是控制器
@RestController
class MyController
@GetMapping("/endpoint")
fun endpoint(): ResponseDto
return ResponseDto(data = "Some data")
data class ResponseDto(val data: String)
测试如下:
@SpringBootTest(
classes = [MyController::class],
webEnvironment = SpringBootTest.WebEnvironment.MOCK
)
@AutoConfigureMockMvc
internal class MyControllerTest(@Autowired private val mockMvc: MockMvc)
@Test
fun `should work`()
mockMvc.perform(MockMvcRequestBuilders.get("/endpoint").accept(MediaType.APPLICATION_JSON))
.andExpect(
content().json(
"""
"data": "Some data"
"""
)
)
build.gradle
文件包含以下依赖项:
def jacksonVersion = "2.10.2"
testImplementation("com.fasterxml.jackson.core:jackson-core:2.10.2")
testImplementation("com.fasterxml.jackson.core:jackson-databind:2.10.2")
testImplementation("com.fasterxml.jackson.core:jackson-annotations:2.10.2")
关于如何让它发挥作用的任何想法?
【问题讨论】:
【参考方案1】:解决方案是使用@WebMvcTest
而不是@SpringBootTest
来注释类。这配置了足够的上下文,测试可以通过MockMvc
与控制器进行交互。
不幸的是,启用@WebMvcTest
有另一个副作用:配置中@Bean
-annotated 方法指定的所有bean 也会被实例化。当这些方法无法在测试环境中执行时(例如,因为它们访问某些环境变量),就会出现问题。
为了解决这个问题,我在测试中添加了注解@ActiveProfiles("test")
,在每个这样的注解方法中添加了@Profile("!test")
。这会抑制对这些方法的调用,并且测试有效。
【讨论】:
【参考方案2】:我不确定,但我认为您需要指定输出的格式。所以像
@GetMapping(value = ["/endpoint"], produces = [MediaType.APPLICATION_JSON])
这样spring就知道把它转换成json而不是说xml什么的。
【讨论】:
添加produces = "application/json"
会将错误更改为以下内容:org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
端点在生产中工作正常,因此必须更改它以进行测试是没有意义的。
啊,我没有意识到这是一个测试特定的情况。在这种情况下,问题可能与您的测试上下文有关,缺少某些东西。我认为您正在尝试手动执行某些操作,以防止弹簧启动已经支持的完整上下文启动。将测试上方的注释更改为 @WebMvcTest(MyController.class) 和自动装配 MockMvc ,它应该做你想做的事(只是旋转 web 层,只有一个控制器),另见:spring.io/guides/gs/testing-web (WebMvcTest 解释了所有底部的路。【参考方案3】:
@EnableWebMvc
可能会解决您的问题。
根据Java Doc:
将此注解添加到@Configuration
类会从WebMvcConfigurationSupport
导入Spring MVC 配置,
e.g.:
@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = MyConfiguration.class)
public class MyConfiguration
要自定义导入的配置,请实现接口 WebMvcConfigurer 并覆盖各个方法,例如:
@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = MyConfiguration.class)
public class MyConfiguration implements WebMvcConfigurer
@Override
public void addFormatters(FormatterRegistry formatterRegistry)
formatterRegistry.addConverter(new MyConverter());
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
converters.add(new MyHttpMessageConverter());
【讨论】:
以上是关于运行 Spring Boot MockMvc 测试时“找不到返回值的转换器”的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot RestApi 测试教程 Mock 的使用
Spring Boot MVC 测试 - MockMvc 始终为空
使用 spring-data-jpa 和 MockMvc 进行 spring boot junit 测试
spring boot 测试无法注入 TestRestTemplate 和 MockMvc