【问题标题】:Use different Spring test context configuration for different test methods对不同的测试方法使用不同的 Spring 测试上下文配置
【发布时间】:2016-05-07 07:45:18
【问题描述】:

我们有一个基于 Spring 的 JUnit 测试类,它利用了一个内部测试上下文配置类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ServiceTest.Config.class)
public class ServiceTest {

    @Test
    public void someTest() {
    ...

    @Configuration
    @PropertySource(value = { "classpath:application.properties" })
    @ComponentScan({ "..." })
    public static class Config {
    ...

最近向 Service 类引入了新功能,应将相关测试添加到 ServiceTest。然而,这些也需要创建不同的测试上下文配置类(现有 Config 类的内部相当复杂,如果可能的话,将其更改为同时服务于新旧测试似乎非常困难)

有没有办法实现一个测试类中的某些测试方法使用一个配置类而其他方法使用另一个? @ContextConfiguration 似乎只适用于类级别,因此解决方案可能是为新测试创建另一个测试类,该类将利用其自己的上下文配置类;但这意味着同一个服务类被两个不同的测试类覆盖

【问题讨论】:

    标签: java spring junit junit4 spring-test


    【解决方案1】:

    当我必须解决这个问题时,我会使用这些方法:

    • 在设置方法中手动构建上下文,而不是使用注释。
    • 将通用测试代码移至基类并对其进行扩展。这让我可以使用不同的 spring 上下文运行测试。
    • 上述两者的混合。然后,基类包含从片段(扩展可以覆盖)构建弹簧上下文的方法。这也让我可以覆盖没有意义的测试用例,或者在某些测试中做额外的前/后工作。

    请记住,注释只能解决一般情况。当你离开共同点时,你将不得不复制他们的部分或全部工作。

    【讨论】:

    • 但是,如果我们在内部手动设置,Autowired 注入是否在基类中工作?
    • @pinkpanther:您将测试设置与被测代码混淆了。测试设置不使用@Autowired。我会尽可能避免在测试中注入:它会减慢测试速度,并且更难看到发生了什么。当 IDE 支持“在我运行测试时显示这里注入的内容”时,我会改变主意。
    【解决方案2】:

    根据 Aaron 关于手动构建上下文的建议,我找不到任何好的示例,所以在花了一些时间让它工作后,我想我会发布一个我使用的代码的简单版本,以防它帮助其他人:

    class MyTest {
    
        @Autowired
        private SomeService service;
        @Autowired
        private ConfigurableApplicationContext applicationContext;
    
        public void init(Class<?> testClass) throws Exception {
            TestContextManager testContextManager = new TestContextManager(testClass);
            testContextManager.prepareTestInstance(this);
        }
    
        @After
        public void tearDown() throws Exception {
            applicationContext.close();
        }
    
        @Test
        public void test1() throws Exception {
            init(ConfigATest.class);
            service.doSomething();
            // assert something
        }
    
        @Test
        public void test2() throws Exception {
            init(ConfigBTest.class);
            service.doSomething();
            // assert something
        }
    
        @ContextConfiguration(classes = {
            ConfigATest.ConfigA.class
        })
        static class ConfigATest {
            static class ConfigA {
                @Bean
                public SomeService someService() {
                    return new SomeService(new A());
                }
            }
        }
    
        @ContextConfiguration(classes = {
            ConfigBTest.ConfigB.class
        })
        static class ConfigBTest {
            static class ConfigB {
                @Bean
                public SomeService someService() {
                    return new SomeService(new B());
                }
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-20
      • 2020-01-23
      • 1970-01-01
      • 2016-11-02
      • 2016-12-31
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多