在集成测试中覆盖spring @Configuration

Posted

技术标签:

【中文标题】在集成测试中覆盖spring @Configuration【英文标题】:Overriding spring @Configuration in an integration test 【发布时间】:2019-10-31 10:14:27 【问题描述】:

我有一个这样的spring boot配置类:

@Configuration
public class ClockConfiguration 

    @Bean
    public Clock getSystemClock() 
        return Clock.systemUTC();
    

我有一些这样的集成测试:

@SpringBootTest(classes = MyApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public abstract class AbstractIntegrationTest  


和这样的测试:

public class MiscTests extends AbstractIntegrationTest

    @Test
    public void CreateSomethingThatOnlyWorksInThe Morning_ExpectCorrectResponse() 

    

我希望能够偏移时钟 bean 以在一天的不同时间运行一些测试。我该怎么做?

注意:我看到 several stack overflow answers 与此类似,但我无法让它们工作。

根据其他回复,解决方案似乎应该是这样的:

@SpringBootTest(classes = MyApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public abstract class AbstractIntegrationTest  

    @Configuration
    class MyTestConfiguration 

        @Bean
        public Clock getSystemClock() 
            Clock realClock = Clock.systemDefaultZone();
            return Clock.offset(realClock, Duration.ofHours(9));
        
    

但是那里什么也没有发生。我需要@Import 吗?我需要@Autowired 吗?

谢谢!

【问题讨论】:

【参考方案1】:

当您使用 Spring Boot 时,您可以利用 @MockBean 注释:

@SpringBootTest(classes = MyApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public abstract class AbstractIntegrationTest  

    @MockBean
    private Clock clockMock;

然后,您可以相应且唯一地为每个测试存根该 bean 的公共方法:

@Test
public void CreateSomethingThatOnlyWorksInThe Morning_ExpectCorrectResponse() 
     when(clockMock.getTime()).thenReturn(..);

根据@MockBean的javadoc:

上下文中定义的任何现有的相同类型的单个 bean 将 被模拟替换。

【讨论】:

嗯,我很困惑。当你说: atMockBean private Clock clockMock;你的意思是:atMockBean public ClockConfiguration mockClock;请记住,我要覆盖(或模拟)的类称为“ClockConfiguration”。无论如何,当我添加我认为你的意思时,我收到了这个错误:“java.lang.IllegalStateException: Failed to load ApplicationContext” @user952342 你不能用模拟框架过度配置。要覆盖配置,您需要 Testconfiguration 。如果你使用 Mock,你需要 Mock the Clock,而不是配置。【参考方案2】:

你需要的是@TestConfiguration注解https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/context/TestConfiguration.html

@RunWith(SpringRunner.class)
public class ClockServiceImplIntegrationTest 

    @TestConfiguration
    static class TestOverridingClockServiceConfiguration 

        @Bean
        public ClockService clockService() 
            return new ClockServiceImpl();
        
    

    @Autowired
    private ClockService clockService;

    @MockBean
    private ClockRepository clockRepository;

    // write test cases here

如果你有现有的配置,你可以 c

【讨论】:

以上是关于在集成测试中覆盖spring @Configuration的主要内容,如果未能解决你的问题,请参考以下文章

在集成测试中覆盖 bean

spring boot集成redis

在测试中使用 Spring @ConfigurationProperties 读取地图

如何使用Spring + EasyMock做Java单元测试

集成测试覆盖率工具 codecov

如何为基于 http 的集成测试生成覆盖率报告?