java 针对不同的测试方法使用不同的 Spring 测试上下文配置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35086806/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:43:14  来源:igfitidea点击:

Use different Spring test context configuration for different test methods

javaspringjunitjunit4spring-test

提问by hammerfest

We have a Spring based JUnit test class which is utilizing an inner test context configuration class

我们有一个基于 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 {
    ...

New functionalities have been recently introduced to the Service class, for which the concerned tests should be added to ServiceTest. However these would also require a different test context configuration class to be created (the internals of the existing Config class are fairly complex and change it to serve both old and new tests seems to be be extremely difficult if possible at all)

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

Is there a way to achieve that certain test methods in one test class would use one config class and other methods would use another? @ContextConfigurationseems to be applicable only on class level, so solution could be to create another test class for the new tests which would utilize its own context configuration class; but it would mean that the same Service class is being covered via two different test classes

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

采纳答案by Aaron Digulla

I use these approaches when I'm have to solve this:

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

  • Manually build the context in a setup method instead of using annotations.
  • Move the common test code to a base class and extend it. That allows me to run the tests with different spring contexts.
  • A mix of the two above. The base class then contains methods to build spring contexts from fragments (which the extensions can override). That also allows me to override test cases which don't make sense or do extra pre/post work in some tests.
  • 在设置方法中手动构建上下文而不是使用注释。
  • 将公共测试代码移至基类并对其进行扩展。这允许我使用不同的 spring 上下文运行测试。
  • 以上两者的混合。然后基类包含从片段(扩展可以覆盖)构建 spring 上下文的方法。这也允许我覆盖没有意义的测试用例或在某些测试中做额外的前/后工作。

Keep in mind that annotations only solve generic cases. You'll have to replicate some or all of their work when you leave the common ground.

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

回答by Andy

With Aaron's suggestion of manually building the context I couldn't find any good examples so after spending some time getting it working I thought I'd post a simple version of the code I used in case it helps anyone else:

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

    }
}