Search code examples
javaspringspring-test

Spring: @BootstrapWith for ApplicationContext


Currently I use @BootstrapWith annotation in conjunction with custom class, which is simply sets some system properties used in test. However (as far as I understand it) those properties are being set each time TestContextManager instantiates test and TestContext with it:

@BootstrapWith is a class-level annotation that is used to configure how the Spring TestContext Framework is bootstrapped

spring.io

Is there any way to set properties once before ApplicationContext is started?

Edit:

I cannot use @RunWith(SpringJUnit4ClassRunner.class) due to parameterized tests, which require @RunWith(Parameterized.class). I use SpringClassRule and SpringMethodRule instead

Additionally I run not only parameterized tests, but ordinary tests as well. Thus I cannot simply extend Parameterized runner


Solution

  • I think that the most basic way of setting some properties before ApplicationContext sets up is to write custom runner, like that:

    public class MyRunner extends SpringJUnit4ClassRunner {
    
        public MyRunner(Class<?> clazz) throws InitializationError {
            super(clazz);
            System.setProperty("sample.property", "hello world!");
        }
    
    }
    

    And then you can use it instead your current runner.

    @RunWith(MyRunner.class)
    @SpringBootTest
    //....
    

    If your current runner seems to be declared final, you can possibly use aggregation (but I have not tested in) instead of inheritance.

    Here you can find a sample Gist where this runner is used and property gets successfully resolved.

    update

    If you don't want to use custom Runner (although you could have several runners setting properties for each case - with parameters, without parameters, and so on). You can use @ClassRule which works on static fields/methods - take a look at the example below:

    @ClassRule
    public static ExternalResource setProperties() {
        return new ExternalResource() {
            @Override
            public Statement apply(Statement base, Description description) {
                System.setProperty("sample.property", "hello world!");
                return super.apply(base, description);
            }
        };
    }
    

    This static method is to be placed in your test class.