嵌套配置无法按预期工作

时间:2016-09-17 12:56:42

标签: spring-boot

我正在使用spring boot工作,我们刚刚升级到1.4.0版本.RELEASE。作为版本升级的一部分,我们已经开始在抽象集成测试类中使用@SpringBootTest注释。阅读the documentation之后,听起来我们应该能够使用嵌套的@ TestConfiguration-annotated配置类来覆盖特定测试期间的bean定义。这对我们不起作用,而是我们试图覆盖的非测试bean仍在使用。

有趣的是,似乎模拟测试bean和生产bean的用法实际上是在同一个测试中交织在一起,就像两个bean在应用程序上下文中并排存在一样。此外,似乎集成测试以某种方式运行的顺序会影响此行为。我想知道这是否是我们错误配置的,或者是否还有其他事情发生。

编辑:

集成测试继承的抽象类如下所示:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles({"local", "test"})
public abstract class BaseIntegrationTest {

    @Value("${local.server.port}")
    protected int port;
}

我们看到奇怪行为的集成测试看起来像这样:

public class WebhookProcessorIT extends BaseIntegrationTest {

    @TestConfiguration
    public static class Config {
        @Bean
        @Primary
        public WebhookTask webhookTask() {
            return mock(WebhookTask.class);
        }
    }

    // sometimes the mock above is used and sometimes
    // the actual production bean is used
    @Autowired
    private WebhookTask task;

    @Before
    public void setup() {
        when(task.process(any())).thenReturn(true);
    }

    // tests ...
}

这就是根应用程序上下文类的样子:

@EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class)
@SpringBootApplication
public class Application {
    private static final Logger log = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        final SpringApplication app = new SpringApplication(Application.class);
        app.setBannerMode(Banner.Mode.OFF);
        app.run(args);
    }
}

编辑:

我也尝试使用@MockBean,如下所示:

public class WebhookProcessorIT extends BaseIntegrationTest {

    @MockBean
    private WebhookTask task;

但测试运行时我得到的结果相同。我可以看到Spring在测试设置期间查看日志时尝试使用我提供的模拟覆盖生产bean:

build   15-Sep-2016 09:09:24    2016-09-15 09:09:24 [34mINFO [0;39m [36m[DefaultListableBeanFactory][0;39m (main) Overriding bean definition for bean 'productionWebhookTask' with a different definition

然而,当涉及到测试执行时,我仍然可以看到正在使用的生产bean:

build   15-Sep-2016 09:09:29    2016-09-15 09:09:29 [39mDEBUG[0;39m [36m[WebhookSupplier][0;39m (WebhookProcessor) Received webhook with ID '1234' from queue.
build   15-Sep-2016 09:09:30    2016-09-15 09:09:30 [39mDEBUG[0;39m [36m[WebhookSupplier][0;39m (WebhookProcessor) Received webhook with ID '5678' from queue.
build   15-Sep-2016 09:09:30    2016-09-15 09:09:30 [39mDEBUG[0;39m [36m[ProductionWebhookTask][0;39m (WebhookProcessor) Received webhook with ID '1234' for processing // production webhook task bean still being used for webhook '1234'
build   15-Sep-2016 09:09:30    2016-09-15 09:09:30 [39mDEBUG[0;39m [36m[WebhookSupplier][0;39m (WebhookProcessor) Deleting webhook with id '5678' from queue. // mock bean causes production logic to be skipped and we just delete webhook '5678'
// More logs from production webhook task operating on webhook with id '1234' and causing the test to fail

2 个答案:

答案 0 :(得分:0)

无论如何,您可以使用 @Profile(" test")和使用@Profile(" production")的真实注释来为您的测试bean添加注释

并在您的属性文件中输入属性 spring.profiles.active = test

来自文档

  

与常规@Configuration类不同,使用@TestConfiguration   不会阻止自动检测@SpringBootConfiguration。

     

与嵌套的@Configuration类不同,后者将用于代替   应用程序的主要配置,嵌套的@TestConfiguration   除了应用程序的主要内容之外,还将使用class   配置。

答案 1 :(得分:0)

由于您使用的是Spring Boot 1.4.0版,因此您可以继续使用新引入的注释 @MockBean ,而不是使用不同的配置类来模拟原始bean。它很直接,非常适合您的使用案例。

Here you go with an example from the documentation