为不同的测试方法使用不同的Spring测试上下文配置

14
我们有一个基于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似乎只适用于类级别,因此解决方案可能是为新测试创建另一个测试类,该测试类将利用自己的上下文配置类;但这意味着同一个Service类将通过两个不同的测试类进行覆盖。
2个回答

16

在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());
            }
        }

    }
}

4
我在解决这个问题时采用以下方法:
  • 手动在设置方法中构建上下文,而不是使用注释。
  • 将公共测试代码移至基类并进行扩展。这使我可以使用不同的spring上下文运行测试。
  • 以上两种方法的混合使用。基类包含从片段构建spring上下文的方法(可被扩展覆盖)。这也允许我覆盖一些没有意义的测试用例或在某些测试中做额外的前/后工作。
请记住,注释只能解决通用情况。当您离开常规情况时,您需要复制一些或所有的工作。

如果我们在基类中手动设置,@Autowired注入是否会起作用? - pinkpanther
@pinkpanther:你把测试设置和被测试的代码搞混了。测试设置不使用@Autowired。我尽可能避免在测试中进行注入,因为这会减慢测试速度并使情况变得更加复杂。当IDE支持“运行测试时展示我注入了什么”,我会改变我的想法。 - Aaron Digulla
完全同意@AaronDigulla的观点,如此处所示https://stackoverflow.com/questions/76901740/difference-when-executing-tests-via-springjunitconfig-vs-springboottest和这里https://stackoverflow.com/questions/76876873/spring-boot-property-resolution-fails-tests-at-build-time-when-adding-a-profile以及这里https://stackoverflow.com/questions/76956597/testing-springbatch-job-via-independent-junit-5-based-test。 - Simeon Leyzerzon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接