Spring boot &引用;未找到返回值“的转换器”;在运行Spring Boot MockMvc测试时

Spring boot &引用;未找到返回值“的转换器”;在运行Spring Boot MockMvc测试时,spring-boot,kotlin,jackson,spring-boot-test,Spring Boot,Kotlin,Jackson,Spring Boot Test,我正在尝试创建一个Spring引导控制器的MockMvc测试。我特别不希望整个应用程序上下文被旋转起来,因此我将上下文限制在所讨论的控制器上。但是,测试失败,500的日志输出如下: 2020-03-03 13:04:06.904 WARN 8207 --- [ main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNot

我正在尝试创建一个Spring引导控制器的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引导上下文似乎不知道如何找到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")

关于如何实现这一点有什么想法吗?

我不确定,但我认为您需要指定输出的格式。大概是

@GetMapping(value = ["/endpoint"], produces = [MediaType.APPLICATION_JSON])

因此spring知道如何将其转换为json,而不是说XML或其他什么。

解决方案是使用
@WebMvcTest
而不是
@springbootest
来注释该类。这配置了足够的上下文,测试可以通过
MockMvc
与控制器交互

不幸的是,启用
@WebMvcTest
还有另一个副作用:配置中由
@Bean
注释的方法指定的所有Bean也被实例化。当这些方法无法在测试环境中执行时(例如,因为它们访问某些环境变量),这是一个问题


为了解决这个问题,我将注释
@ActiveProfiles(“test”)
添加到测试中,并将
@Profile(“!test”)
添加到每个这样的注释方法中。这会抑制对这些方法的调用,测试也会起作用。

@EnableWebMvc
可能会解决您的问题。 根据Java文档:

将此注释添加到
@Configuration
类将从
WebMvcConfigurationSupport
导入Spring MVC配置

e.g.:
 @Configuration
 @EnableWebMvc
 @ComponentScan(basePackageClasses = MyConfiguration.class)
 public class MyConfiguration {

 }
要自定义导入的配置,请实现接口WebMVCConfiguer并覆盖各个方法,例如:

 @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());
           }

 }
@配置
@EnableWebMvc
@ComponentScan(basePackageClasses=MyConfiguration.class)
公共类MyConfiguration实现WebMVCConfiguer{
@凌驾
公共void addFormatters(FormatterRegistry FormatterRegistry){
addConverter(新的MyConverter());
}
@凌驾

public void configureMessageConverters(列表添加
products=“application/json”
将错误更改为以下内容:
org.springframework.web.HttpMediaTypeNotAcceptableException:找不到可接受的表示形式
端点在生产中工作正常,因此在测试中必须更改它是没有意义的。啊,我没有意识到这是一种特定于测试的情况。在这种情况下,问题就出现了可能是您的测试上下文中缺少了某些内容。我认为您正在尝试手动执行某些操作,以防止完整的上下文启动,spring boot已经支持该操作。请将测试上方的注释更改为@WebMvcTest(MyController.class)和autowire MockMvc,它应该可以执行您想要的操作(只是旋转web层,只有一个控制器),另请参见:(WebMvcTest在底部进行了详细说明。