【问题标题】:Unable to autowire RestTemplate for unit test无法为单元测试自动装配 RestTemplate
【发布时间】:2018-09-17 20:02:24
【问题描述】:

我有一个服务,它使用RestTemplate 的自动装配实例,如下所示

@Service
class SomeAPIService {
    private RestTemplate restTemplate;

    SomeAPIService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
        this.restTemplate.setRequestFactory(HttpUtils.getRequestFactory());
    }
}

在非测试环境中一切正常。但是当我尝试在测试配置文件中运行以下单元测试时,它开始抱怨无法自动装配休息模板。

@RunWith( SpringJUnit4ClassRunner.class )
@SpringBootTest(classes = MyApplication.class, webEnvironment = RANDOM_PORT, properties = "management.port:0")
@ActiveProfiles(profiles = "test")
@EmbeddedPostgresInstance(flywaySchema = "db/migration")
public abstract class BaseTest {
}

@SpringBootTest(classes = SomeAPIService.class)
public class SomeAPIServiceTest extends BaseTest {
    @Autowired
    SomeAPIService someAPIService;

    @Test
    public void querySomeAPI() throws Exception {
        String expected = someAPIService.someMethod("someStringParam");
    }
}

以下是详细的例外情况-

原因: org.springframework.beans.factory.UnsatisfiedDependencyException: 创建名为“someAPIService”的 bean 时出错:不满足的依赖关系 通过构造函数参数0表示;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException: 否 'org.springframework.web.client.RestTemplate' 类型的限定 bean 可用:预计至少有 1 个符合 autowire 条件的 bean 候选人。依赖注释:{}

有什么线索吗?

【问题讨论】:

    标签: java spring-boot junit mockito


    【解决方案1】:

    以下帮助我自动装配了正确的依赖项。解决方案是在提供给SpringBootTest 的类列表中也包含RestTemplate.class

    @SpringBootTest(classes = {RestTemplate.class, SomeAPIService.class})
    class SomeAPIService {
        @Autowired
        SomeAPIService someAPIService;
    
        @Test
        public void querySomeAPI() throws Exception {
            String expected = someAPIService.someMethod("someStringParam");
        }
    }
    

    @Emre 的回答有助于引导我找到最终解决方案。

    【讨论】:

      【解决方案2】:

      您试图在不满足其依赖关系的情况下自动装配 SomeAPIService。您应该将 Rest Template 注入 SomeAPIService。但是你得到了 Rest Template 的 NoSuchBeanDefinitionException。

      看看如何注入它:

      How to autowire RestTemplate using annotations

      【讨论】:

      • 我确实有一个 HttpConfiguration 类,使用 Configuration 注释,并带有 RestTemplate 的 bean 定义
      • 正如我所提到的,我很难理解为什么在非测试环境中一切都运行良好,而在测试环境中中断。我一直像这样自动装配,没有为其他单元测试注入依赖项,也从未遇到过问题。
      • 尝试将 @SpringBootTest(classes = SomeAPIService.class) 更改为 @SpringBootTest(classes = MyApplication.class) 根据 Spring Boot 文档:“classes 用于加载 ApplicationContext 的注释类。”跨度>
      • 谢谢埃姆雷。这很有帮助,确实帮助我解决了这个问题,但现在活跃的个人资料已经困扰着我了。我的应用程序需要额外的活动配置文件才能构建某些依赖项。我正在像这样mvn test -P myActiveProfile 向 maven 测试提供活动配置文件,但是当我在通常的运行中放弃指定 myActiveProfile 时,它​​给了我同样的错误。接线问题,但类型不同
      • 使用@SpringBootTest(classes = MyApplication.class)实际上是在运行整个应用程序而不是单元测试用例
      【解决方案3】:

      替代答案是 - 使用TestRestTemplate

      From official docs >>>

      TestRestTemplate 可以在您的集成测试中直接实例化,如下例所示:

      public class MyTest {
      
          private TestRestTemplate template = new TestRestTemplate();
      
          @Test
          public void testRequest() throws Exception {
              HttpHeaders headers = this.template.getForEntity(
                      "https://myhost.example.com/example", String.class).getHeaders();
              assertThat(headers.getLocation()).hasHost("other.example.com");
          }
      
      }
      

      或者,如果您将@SpringBootTest 注释与WebEnvironment.RANDOM_PORTWebEnvironment.DEFINED_PORT 一起使用,您可以注入一个完全配置的TestRestTemplate 并开始使用它。如有必要,可以通过 RestTemplateBuilder bean 应用其他自定义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-29
        • 2016-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-03
        • 2011-11-20
        • 2020-02-09
        相关资源
        最近更新 更多