Spring Tests Defined Using Meta-Annotation

0

In order to provide Spring testing functionality to standard JUnit tests, we need to first make sure to run the test class with @RunWith annotation set to SpringJUnit4ClassRunner and provide configuration classes using @ContextConfiguration or @ContextHierarchy.

You can read other scenarios related to @ContextConfiguration and @ContextHierarchy here.

In this article, we will see how to use composed annotation annotated with either @ContextConfiguration or @ContextHierarchy to build the application context.

Composed @ContextConfiguration Annotation

We provide the configuration classes or the XML context file locations using @ContextConfiguration. See here for an example. One can also declare the @ContextConfiguration as a meta-annotation, that is, a custom annotation which is composed of @ContextConfiguration.

ComposedContextConfiguration:

package com.javarticles.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComposedContextConfiguration {
}

Spring Tests using composed annotation

We will now use the above defined meta-annotation to define spring based tests.
A:

package com.javarticles.spring;

public class A {
}

ClassWithComposedAnnotationContainingContextConfiguration:

package com.javarticles.spring;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ComposedContextConfiguration
public class ClassWithComposedAnnotationContainingContextConfiguration {

    @Autowired
    private A beanA;
    
    @Test
    public void verifyBeanAConfigured() {
        assertNotNull(beanA);
    }
    
    @Configuration
    static class Config {
        @Bean
        A beanA() {
            return new A();
        }
    }
}

Spring looks for @ContextConfiguration and @ContextHierarchy not in the root test class but also its super classes. Likewise it also traverses through the annotations declared at each class to see if it can find @ContextConfiguration or @ContextHierarchy and this includes even the meta-annotations.
Output:

Mar 02, 2016 2:47:56 AM org.springframework.test.context.support.AbstractContextLoader generateDefaultLocations
INFO: Could not detect default resource locations for test class [com.javarticles.spring.ClassWithComposedAnnotationContainingContextConfiguration]: no resource found for suffixes {-context.xml}.
Mar 02, 2016 2:47:56 AM org.springframework.test.context.support.AbstractDelegatingSmartContextLoader processContextConfiguration
INFO: AnnotationConfigContextLoader detected default configuration classes for context configuration [ContextConfigurationAttributes@27abe2cd declaringClass = 'com.javarticles.spring.ClassWithComposedAnnotationContainingContextConfiguration', classes = '{class com.javarticles.spring.ClassWithComposedAnnotationContainingContextConfiguration$Config}', locations = '{}', inheritLocations = true, initializers = '{}', inheritInitializers = true, name = [null], contextLoaderClass = 'org.springframework.test.context.ContextLoader'].
Mar 02, 2016 2:47:56 AM org.springframework.test.context.support.DefaultTestContextBootstrapper getDefaultTestExecutionListenerClassNames
INFO: Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
Mar 02, 2016 2:47:56 AM org.springframework.test.context.support.DefaultTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [javax/servlet/ServletContext]
Mar 02, 2016 2:47:56 AM org.springframework.test.context.support.DefaultTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
Mar 02, 2016 2:47:56 AM org.springframework.test.context.support.DefaultTestContextBootstrapper instantiateListeners
INFO: Could not instantiate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
Mar 02, 2016 2:47:56 AM org.springframework.test.context.support.DefaultTestContextBootstrapper getTestExecutionListeners
INFO: Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@1ae369b7, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@6fffcba5, org.springframework.test.context.support.DirtiesContextTestExecutionListener@34340fab]
Mar 02, 2016 2:47:56 AM org.springframework.context.support.GenericApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.GenericApplicationContext@506e6d5e: startup date [Wed Mar 02 02:47:56 PST 2016]; root of context hierarchy

Download the source code

This was an example about using spring composed @ContextConfiguration.

You can download the source code here: springComponentAnnotationExample.zip

About Author

Ram's expertise lies in test driven development and re-factoring. He is passionate about open source technologies and loves blogging on various java and open-source technologies like spring. You can reach him at rsatish.m@gmail.com

Comments are closed.