Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Import vs @ContextConfiguration for importing beans in unit tests

I was able to set up and successfully run three different test configurations with SpringBoot 1.5.3

Method #1. Importing Bean with use of @Import annotation

@RunWith(SpringJUnit4ClassRunner.class)
@Import({MyBean.class})
public class MyBeanTest() {
    @Autowired
    private MyBean myBean;
}

Method #2. Importing Bean with use of @ContextConfiguration annotation

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyBean.class})
public class MyBeanTest() {
    @Autowired
    private MyBean myBean;
}

Method #3 (with internal class configuration; based on the official blog post)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class)
public class MyBeanTest() {

    @Configuration
    static class ContextConfiguration {
        @Bean
        public MyBean myBean() {
            return new MyBean();
        }
    }

    @Autowired
    private MyBean myBean;

}

Taking into account @Import annotation documentation

Indicates one or more {@link Configuration @Configuration} classes to import.

and the fact that MyBean is not a configuration class, but a bean class annotated with @Component annotation it looks like Method #1 is not correct.

From @ContextConfiguration documentation

{@code @ContextConfiguration} defines class-level metadata that is used to determine how to load and configure an {@link org.springframework.context.ApplicationContext ApplicationContext} for integration tests.

Sounds like it is better applicable to unit tests, but still, should load a kind of a configuration.

Methods #1 and #2 are shorter and simpler. Method #3 looks like a correct way.

Am I right? Are there other criteria why I should use method #3, like performance or something else?

like image 359
humkins Avatar asked Jun 05 '17 07:06

humkins


People also ask

What is the use of @import in spring?

@Import annotation in Spring allows you to load bean definitions from one or more another @Configuration files or Components. You might not want to configure all the beans in one configuration file.

What is @ContextConfiguration in spring?

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

What XML file does Spring use when creating the application context in this integration 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

You actually don't need to specify the loader if you go with option #3. From the doc In addition to the example from the doc you can override the env. with @TestPropertySource if you need to inject properties in the environment without using the real ones.

@RunWith(SpringRunner.class)
// ApplicationContext will be loaded from the
// static nested Config class
@ContextConfiguration
@TestPropertySource(properties = { "timezone = GMT", "port: 4242" })
public class OrderServiceTest {

    @Configuration
    static class Config {

        // this bean will be injected into the OrderServiceTest class
        @Bean
        public OrderService orderService() {
            OrderService orderService = new OrderServiceImpl();
            // set properties, etc.
            return orderService;
        }
    }

    @Autowired
    private OrderService orderService;

    @Test
    public void testOrderService() {
        // test the orderService
    }

}
like image 146
Pär Nilsson Avatar answered Oct 07 '22 17:10

Pär Nilsson