【问题标题】:SpringBoot @WebMvcTest, autowiring RestTemplateBuilderSpringBoot @WebMvcTest,自动装配 RestTemplateBuilder
【发布时间】:2017-05-31 02:44:21
【问题描述】:

我在测试 Spring 控制器时遇到了问题。 我在我的测试类中使用注释@WebMvcTest。 当我运行测试时,我得到这个错误: 没有可用的“org.springframework.boot.web.client.RestTemplateBuilder”类型的合格 bean

我将 RestTemplate 用于项目中的其他类,因此我在主类中定义了一个 bean:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder.build();
}

为了让它工作,我必须这样定义我的 restTemplate bean:

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

是 @WebMvcTest 注释有问题还是我遗漏了什么?

谢谢

【问题讨论】:

  • 刚刚跳进了同一个问题,对我来说它看起来像一个错误,找不到太多的东西。有更新吗?

标签: java spring spring-boot junit resttemplate


【解决方案1】:

是的,这确实像一个错误。
但是,您可以通过将 @AutoConfigureWebClient 与现有的 @WebMvcTest 一起添加到您的测试类来轻松解决它

【讨论】:

  • 这个解决方案为我解决了这个问题。当我们尝试使用测试切片时,感觉就像我们正在进入无证领域。 Spring 在测试期间为我们创建了一些 bean,但有些——比如 RestTemplateBuilder——神秘地不存在,除非我们按照你的建议撒上这种神奇的仙尘。
  • 我同意 @Gary,我为此提出了一个问题 (github.com/spring-projects/spring-boot/issues/8784),但它已作为 github.com/spring-projects/spring-boot/issues/7999 的副本关闭。
  • 但是我已经改变了关于这是一个错误的想法,我认为这只是测试切片如何在自动装配方面绊倒你以及你不应该做任何事实的一个例子使用切片功能时任何可用 bean 的假设。感觉就像一个错误,因为 RestTemplate 似乎与测试 MVC 齐头并进,但问问自己,你是否真的在测试中使用了那个 RestTemplate?您可能需要根据测试期间扫描的内容来重构您的应用程序。
【解决方案2】:

当您向@Bean 定义添加任何参数时,这意味着您正在寻找提到要注入的 T 类型的 bean。 改变这个:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder.build();
}

 @Bean
    public RestTemplate restTemplate() {

       RestTemplateBuilder builder=new RestTemplateBuilder(//pass customizers);

        return builder.build();
    }

【讨论】:

  • 好的,但是根据 Spring 文档,Spring-Boot 提供了一个 RestTemplateBuilder bean,这就是为什么我不必再创建一个 -> spring.io/guides/gs/consuming-rest。除了在我启动我的应用程序时一切正常之外,它只是在单元测试中......
【解决方案3】:

当我编写控制器测试时,我通常更喜欢为所有协作者使用模拟。这使得验证您的 bean 是否以您期望的值被调用变得非常容易,而无需实际执行调用。

使用 WebMvcTest 这非常容易实现,下面是一个给出您的 RestTemplate Bean 的示例。

@RunWith(SpringRunner.class)
@WebMvcTest(SomeController.class)
public class SomeControllerTest {

   @MockBean
   private RestTemplate restTemplate;

   @Test
   public void get_WithData() {
      mockMvc.perform(get("/something")).andExpect(status().isOk());
      verify(restTemplate, times(1)).getForObject("http://localhost:8080/something", SomeClass.class);
   }
}

【讨论】:

  • 但是我正在测试的控制器不使用 RestTemplate。如果我在我的测试类中创建一个 MockBean 它可以工作:@MockBean private RestTemplateBuilder restTemplateBuilder;但是这个 mockBean 没有被使用,它是一种避免这个错误的解决方法,但是它在我的测试类中添加了无用的属性......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-10
  • 2015-07-14
  • 2017-10-12
  • 2017-09-09
  • 2015-07-14
  • 2019-04-28
  • 2018-02-15
相关资源
最近更新 更多