Manuel Jordan
Manuel Jordan

Reputation: 16281

How retrieve the Spring ApplicationContext through TestRule

I want to know if is possible retrieve the ApplicationContext through a TestRule.

Here TestRule is used how an approach to avoid hierarchy among Test Classes, it with the purpose to reuse infrastructure configuration but in this case the structure needed are @Beans already created by Spring.

To keep simple the code to share, lets suppose we need retrieve the Environment object.

I have tried these two approaches:

One

@WebAppConfiguration
@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})
public class ManolitoRule implements TestRule {

    @Autowired
    private Environment environment;

    private static final Logger logger = LoggerFactory.getLogger(ManolitoRule.class.getSimpleName());

    @Override
    public Statement apply(Statement base, Description description) {

        if(environment == null) {
            logger.error("NULL");
        }
        else {
            logger.info("Profiles: {}", Arrays.toString(environment.getActiveProfiles()));
        }

        return new Statement() {

                //The @Before configuration should go here now
                ...


            }


        };


    }

}

And

public class ManolitoTest {

    private static final Logger logger = LoggerFactory.getLogger(ManolitoTest.class.getSimpleName());

    @Rule
    public ManolitoRule manolitoRule = new ManolitoRule();

    @Test
    public void manolitoTest() {

        ...

    }

}

The environment is null

Two

public class ManolitoRule implements TestRule {

    private final Environment environment;

    public ManolitoRule(Environment environment) {
        this.environment = environment;
    }

    private static final Logger logger = LoggerFactory.getLogger(ManolitoRule.class.getSimpleName());

    @Override
    public Statement apply(Statement base, Description description) {

        if(environment == null) {
            logger.error("NULL");
        }
        else {
            logger.info("Profiles: {}", Arrays.toString(environment.getActiveProfiles()));
        }

        return new Statement() {

            //The @Before configuration should go here now    
            ....


        };


    }

}

And

@WebAppConfiguration
@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class ManolitoTest {

    private static final Logger logger = LoggerFactory.getLogger(ManolitoTest.class.getSimpleName());

    @Autowired
    private Environment environment;

    @Rule
    public ManolitoRule manolitoRule = new ManolitoRule(environment);

    @Test
    public void manolitoTest() {

        ...

    }

}

Again the environment is null

Does exist a correct configuration to accomplish this configuration?

I have the impression that the life cycles between JUnit and Spring Framework are the reason of this situation.

Note: If an abstract class is used all work fine. But consider the scenario to avoid hierarchy and chain @Rules, such as ManolitoRule working with SpringClassRule and SpringMethodRule

Upvotes: 0

Views: 231

Answers (2)

Sam Brannen
Sam Brannen

Reputation: 31227

Approach Two is close to a working solution and just needs the following changes.

  1. Annotate the test class with @RunWith(SpringRunner.class).
  2. Configure an instance of ManolitoRule as a bean in the test's ApplicationContext.
  3. Annotate the ManolitoRule constructor with @Autowired.
  4. Annotate the manolitoRule field in the test class with @Rule and @Autowired.

Note: this technique does not work in conjunction with the Spring rules (SpringClassRule and SpringMethodRule). This technique only works in conjunction with the SpringRunner.

Upvotes: 1

David Han
David Han

Reputation: 43

have you tried to

@Autowired 
private Environment env;

Edit: Try add this as well

@RunWith(SpringJUnit4ClassRunner.class)

Upvotes: 1

Related Questions