Pages

Testing a Spring Profile Bean

We have seen in a previous post how to use the Spring Profile annotation to let the framework select which Bean to load at runtime. Let's see now how to test this behavior with JUnit.

Say that for some peculiar reason, my Web Application needs to have different beans in different environments. To address this delicate matter, we can create a Spring Configuration class that autowires objects implementing classes in the same hierarchy using a specific factory method.

For instance, here is how I could let Spring know that I want to create CharSequence Beans in an application:
@Configuration
public class CharSeqConfig {
    @Bean
    @Profile("dev")
    public CharSequence myString() {
        return new String("String");
    }

    @Bean
    @Profile("prod")
    public CharSequence myStringBuilder() {
        StringBuilder sb = new StringBuilder();
        sb.append("StringBuilder");
        return sb;
    }
}
When the "dev" profile is specified, Spring will use the myString() method when asked to wire a CharSequence bean. When in "prod", myStringBuilder() will be selected instead.

Testing this code with JUnit it is not much more complicated than the usual job we have already seen, basically, we have to specify which profile we want check using the ActiveProfiles annotation. However, usually we want to keep together the same tests for different profiles, and the nice thing is that we can easily do it, using static classes:
public class CharSeqConfigTest {
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes=CharSeqConfig.class)
    @ActiveProfiles("dev")
    public static class DevCharSeqTest {
        @Autowired
        private CharSequence charSeq;
        
        @Test
        public void testCharSeq() {
          assertThat(charSeq.toString(), is("String"));
        }
    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes=CharSeqConfig.class)
    @ActiveProfiles("prod")
    public static class ProdCharSeqTest {
        @Autowired
        private CharSequence charSeq;
        
        @Test
        public void testCharSeq() {
          assertThat(charSeq.toString(), is("StringBuilder"));
        }
    }
}
A minor nuisance is that we have to tell to STS which family of tests we want to run with JUnit:
However it pays off well.
Having seen the green light for both the profiles, I have pushed the code on GitHub, both for the configuration class and the JUnit test case.

I have written this post while reading the third chapter, Advanced wiring, of Spring in Action, Fourth Edition by Craig Walls. I ported the original code to a Maven Spring Boot Web project on the STS IDE, using AspectJ annotations instead of using the classic xml configuration. I have also done a few minor changes to keep the post as slim and readable as possible. Here I have used CharSequence as root for my bean hierarchy instead of DataSource. In this way my example code makes less sense, but it give some immediate satisfaction.

No comments:

Post a Comment