【问题标题】:SpringBoot integration test - TestRestTemplate doesn't reach controller and get 404 instead of 200Spring Boot 集成测试 - TestRestTemplate 没有到达控制器并获得 404 而不是 200
【发布时间】:2017-11-29 22:09:22
【问题描述】:

我试图在 springboot 中进行一些集成测试,因此我使用 @SpringBootTest 注释构建了一些示例测试。我的样本测试是:

     @RunWith(SpringRunner.class)
     @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
     @ContextConfiguration(classes = IntegrationTestConfig.class)
        public class WeatherForCityIT {


            @Autowired
            private TestRestTemplate restTemplate;



            @Test
            public void getWeatherForExistingCity() throws Exception {

                String existingCity = "London";

                ResponseEntity<String> responseEntity = restTemplate.getForEntity("/weather/{cityName}",String.class,existingCity.toString());
                Assertions.assertThat(responseEntity).isNotNull();


            }
        }

并具有以下控制器类

@RestController
@RequestMapping("/weather")
public class ChartController {

    private WeatherForecastAPI weatherForecastAPI;

    @Autowired
    public void setWeatherForecastAPI(WeatherForecastAPI weatherForecastAPI) {
        this.weatherForecastAPI = weatherForecastAPI;
    }

    @GetMapping("/{cityName}")
    public List<WeatherForecastDTO> get5daysForecast(@PathVariable String cityName) {

        weatherForecastAPI.getWeatherForecastByCity(cityWithCountryCode.toString());            
    }

}

不幸的是,在响应正文中,我收到消息 404 Not Found。在调试模式下,我看到它永远不会到达定义的控制器。从配置的角度来看,我是否遗漏了一些东西?我也尝试使用 MockMvc :

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@ContextConfiguration(classes = IntegrationTestConfig.class)
public class WeatherForCityIT {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void getWeatherForExistingCity() throws Exception {

        String existingCity = "London";

        restTemplate.getForEntity("/weather/{cityName}",String.class,existingCity);

        mockMvc.perform(get("/weather/" + existingCity))
               .andDo(print())
               .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

但也没有成功(再次是 404 而不是 202)。

已编辑

配置类如下所示:

@Configuration
@EnableAutoConfiguration
public class IntegrationTestConfig {

    @Bean
    public com.jayway.jsonpath.Configuration configuration() {

        return com.jayway.jsonpath.Configuration.builder()
                                                .jsonProvider(new JacksonJsonProvider())
                                                .mappingProvider(new JacksonMappingProvider())
                                                .options(EnumSet.noneOf(Option.class))
                                                .build();
    }

}

【问题讨论】:

  • 查看您的代码,请求映射看起来不错。您可以做的是检查测试上下文中的可用映射。在您的 WeatherForCityIT 测试类中自动装配 RequestMappingHandlerMapping,并使用 RequestMappingHandlerMapping.getHandlerMethods().keySet(); 访问映射。检查 /weather/{cityName} 路径是否在此列表中。
  • 谢谢伊戈尔,我已经检查过了,我收到了No qualifying bean of type 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping' available,这让我明白了,我没有在这里粘贴完整的代码。我想念@ConfigurationContext ,它指向空配置类。当我删除它时,一切正常。这是为什么 ?为什么指定配置类会导致该错误?
  • 使用@ContextConfiguration,您可以指定要加载哪些@Configuration 类以在您的测试中配置您的ApplicationContext。通常在测试 Spring Boot 应用程序时不需要它。 @SpringBootTest 将自动在使用 @SpringBootApplication 注释的类中搜索您的主要配置。如果您需要调整您的主要配置,最好使用@TestConfiguration 类。你可以找到更多here
  • 好的,但是如何处理没有嵌套的配置。这个配置类在很多其他测试中很常见,所以我不想将它复制粘贴到其他类中。因为@TestConfiguration 用于嵌套配置
  • 尝试使用 @TestConfiguration 而不是 @Configuration 来注释您的 IntegrationTestConfig

标签: spring-boot integration-testing resttemplate mockmvc


【解决方案1】:

您的测试配置类中不需要@EnableAutoConfiguration。因此 IntegrationTestConfig 应如下所示:

@TestConfiguration
public class IntegrationTestConfig {

    @Bean
    public com.jayway.jsonpath.Configuration configuration() {

        return com.jayway.jsonpath.Configuration.builder()
                .jsonProvider(new JacksonJsonProvider())
                .mappingProvider(new JacksonMappingProvider())
                .options(EnumSet.noneOf(Option.class))
                .build();
    }
}

您的 WeatherForCityIT 应与示例代码中的一样:

@RunWith(SpringRunner.class)
     @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
     @ContextConfiguration(classes = IntegrationTestConfig.class)
public class WeatherForCityIT {
     // your code here...
}

关于您收到的异常消息:

没有可用的“com.jayway.jsonpath.Configuration”类型的合格 bean:预期单个匹配 bean,但找到了 2:getConfiguration,configuration)

根据错误消息,您知道您的上下文中有 2 个 bean 相同类型 (com.jayway.jsonpath.Configuration):

  1. 名称为 getConfiguration 的 Bean
  2. 名称为 configuration 的 Bean

bean configuration 在您的 IntegrationTestConfig 中定义,另一个 bean getConfiguration 在您的一个配置类中定义。在您的应用程序的某个地方,您正在按类型自动装配 'com.jayway.jsonpath.Configuration' bean。由于您有 2 个这种类型的 bean,因此 Spring 抱怨异常。

你需要这两种豆子吗?如果没有,请删除其中一个 bean。否则请考虑在自动装配 bean 时使用 @Qualifier 注释。

【讨论】:

  • 我认为这是解决我问题的正确方法。总结一下 - @ContextConfiguration (classes = IntegrationTestConfig.class) 需要引用 @TestConfiguration 类,否则 @Configuration 类会覆盖我从应用程序中的主要配置。现在,@Qualifier 在我的情况下并不是最好的 - 它是集成测试,因此自动装配发生在业务方法中,而不是测试方法中。但是通过分析我可以达到同样的效果。更重要的是,我不需要定义@ContextConfiguration,因为它对 bean 模糊问题没有帮助。感谢@Igor 的帮助!
猜你喜欢
  • 2014-08-12
  • 2020-06-15
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 2017-05-23
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
相关资源
最近更新 更多