Spring 集成测试 - 覆盖 bean 的惯用方式

Spring Integration Tests - idiomatic way of overriding beans

如何以惯用的方式覆盖 Spring(引导)集成测试中的 bean?

到目前为止,我的源配置是这样的:

@Configuration
class ApplicationConfiguration {
  @Bean
  CarsRepository carsRepository() {
    // return some real sql db
  }
}

并像这样进行测试:

@SpringBootTest
class ApplicationISpec extends Specification {
  @Configuration
  @Import(Application.class)
  static class TestConfig {
    @Bean
    @Primary
    CarsRepository testsCarsRepository() {
      // return some in-memory repository
    }
  }

  def "it can do stuff with cars"() {
    // do some REST requests to application and verify it works
    // there is no need to make real calls to real DB
  }
}

第一件事是测试bean testsCarsRepository 方法必须与原始方法不同(这并不明显,并且没有warning/error )。 但最后一个问题是:在集成测试中用 Spring 覆盖 bean 的惯用方法是什么?

当我在 Twitter - Stephane Nicoll 上发布关于方法名称的 WTF 时说 @Primary 不打算用于覆盖测试中的 bean。

那么首选的方式是什么?

您可以将 @Profile@ActiveProfile 注释一起使用来分隔测试和生产配置。例如,将您的测试配置更改为:

@SpringBootTest
@ActiveProfiles("test")
class CarsISpec extends Specification {
    @Configuration
    @Import(Application.class)
    @Profile("test")
    static class TestConfig {
       @Bean
       CarsRepository testsCarsRepository() {
       // return some in-memory repository
       }
  }
}

不要忘记用 @Profile("!test").

标记您的生产配置 ApplicationConfiguration

此外,Spring Boot 提供了许多用于测试的工具(例如,@DataJpaTest 与嵌入式数据库,@MockBean 用于在上下文中模拟 beans 等)Link to doc