Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use different Spring test context configuration for different test methods

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

@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)

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? @ContextConfiguration seems 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

like image 820
hammerfest Avatar asked Jan 29 '16 14:01

hammerfest


People also ask

What is the use of context configuration in spring?

Annotation Type ContextConfiguration. @ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests.

What does SpringBootTest annotation do?

The @SpringBootTest annotation is useful when we need to bootstrap the entire container. The annotation works by creating the ApplicationContext that will be utilized in our tests. We can use the webEnvironment attribute of @SpringBootTest to configure our runtime environment; we're using WebEnvironment.

What kind of testing can be done in spring test module?

The core items for the testing are contained in the modules called spring-boot-test and the configuration is provided by the modules called spring-boot-test-autoconfigure. We can simply use the spring-boot-starter-test in pom. xml and transitively pull all the required dependencies in a Spring application.

Which among the following is used to load the Spring XML configuration for test cases using spring test?

By default the ApplicationContext is loaded using the GenericXmlContextLoader which loads a context from XML Spring configuration files. You can then access beans from the ApplicationContext by annotating fields in your test class with @Autowired , @Resource , or @Inject .


1 Answers

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:

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

    }
}
like image 91
Andy Avatar answered Sep 19 '22 01:09

Andy