Search code examples
javaspringspring-bootjunitannotations

Test class with @Qualifier @Autowired value


I'm testing a class that has @Qualified @Autowired value:

// class under test
class C1() {

    @Autowired
    @Qualified("c1")
    DataSource d1;
    ...
}

DataSource d1 located in config file.

But when I'm testing same class and I'm using separate DataSource which is in test config class:

// test for class
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = testC1Config.class, loader=AnnotationConfigContextLoader.class)
class testC1() {

    @Autowired
    @Qualified("c1Test")
    DataSource d1Test;
    ...
}

// testC1Config
@Configuration
class testC1Config() {

    @Bean
    @Qualified("c1Test")
    DataSource c1Test() {
    ...
    }
}

I get this exception:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=c1)}

says that he only sees DataSource Bean with only Qualifier c1. Have tried to use @Bean(name=c1Test") but I get same result..

How do I make him to see the c1Test DataSource bean in test package?


Solution

  • Okay so I made a work-arround that works.

    (Behind the scenes) For my case I have 2 DataSources in test and src packages, when I'm testing the method in src, he has @Autowired DataSource and he asks to use the bean that is qualified with c1, but since I didnt had c1 DataSource in my testC1Config() I got this exception.

    So instead autowiring a bean and using qualifier with specific name, I wrote the autowired setter with qualifier containing same name in src config bean.

        @Autowired
        @Qualifier("c1")
        public void setDataSource(DataSource dataSource) {
            this.jdbcTemplate = new JdbcTemplate(dataSource);
        }
    

    For my case I'm constructing 2 jdbcTemplates too, this way whenever I run test Bean injects the DataSource I need and do stuff for me before @Test. If doing this way, no bean names required in config, but in services @Qualifier("with_same_name_in_src_and_test").

    Don't know if it's a good approach to this problem, but.... it works.