1

I am trying to test my repository layer using Spring Boot 2.0.1 but when I run my test class, Spring tries to instantiate a Config class not from the test package.

Here is the test code:

TestConfig.class

@Configuration
@Import(value = {TestDatabaseConfig.class})
@Profile("local")
public class TestConfig {

}

TestDatabaseConfig.class

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "logEntityManagerFactory",
        transactionManagerRef = "logTransactionManager",
        basePackages = { "it.xxx.yyy.repository.log" })
@EntityScan(basePackages = {"it.xxx.yyy.model.log", "it.xxx.yyy.common"})
@Profile("local")
public class TestDatabaseConfig {

@Bean("logDataSourceProperties")
public DataSourceProperties logDataSourceProperties() {
    return new DataSourceProperties();
}


@Bean(name = "logDataSource")
public DataSource dataSource(@Qualifier("logDataSourceProperties") DataSourceProperties properties) {
    return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .addScript("classpath:schema.sql")
            .build();
}

@Bean(name = "logEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean logEntityManagerFactory(EntityManagerFactoryBuilder builder,
                                                                      @Qualifier("logDataSource") DataSource logDataSource) {
    return builder.dataSource(logDataSource)
            .packages("it.xxx.model.log")
            .persistenceUnit("log")
            .build();
}

@Bean(name = "logTransactionManager")
public PlatformTransactionManager logTransactionManager(@Qualifier("logEntityManagerFactory")EntityManagerFactory logEntityManagerFactory) {
    return new JpaTransactionManager(logEntityManagerFactory);
}

}

When I run this class

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("local")
public class LogRepositoryTest {

    @Autowired
    private ResultLogRepository resultLogRepository;

    @Test
    public void init(){
    }
}

it says :

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'kafkaProducer': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'kafka.topic.operation' in value "${kafka.topic.operation}"
[...]
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'kafka.topic.operation' in value "${kafka.topic.operation}"

But I cannot understand why it brings up my KafkaProducer.class from my main package (that has @Configuration annotation on it).

0

1 Answer 1

1

In your LogRepositoryTest test class you should indicate the alternate test configuration class that should be taken into account, in your case I think should be the TestConfig.

From Spring Boot documentation:

If you are familiar with the Spring Test Framework, you may be used to using @ContextConfiguration(classes=…​) in order to specify which Spring @Configuration to load. Alternatively, you might have often used nested @Configuration classes within your test.

So annotate LogRepositoryTest with @ContextConfiguration(classes = {TestConfig.class})

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("local")
@ContextConfiguration(classes = {TestConfig.class})
public class LogRepositoryTest {

    @Autowired
    private ResultLogRepository resultLogRepository;

    @Test
    public void init(){
    }
}

UPDATE

Also annotate your configuration class with:

@EnableAutoConfiguration

Something like:

@Configuration
@EnableAutoConfiguration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "logEntityManagerFactory",
        transactionManagerRef = "logTransactionManager",
        basePackages = { "it.xxx.yyy.repository.log" })
@EntityScan(basePackages = {"it.xxx.yyy.model.log", "it.xxx.yyy.common"})
@Profile("local")
public class TestDatabaseConfig {
//...
}

UPDATE 2

For error:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' available: expected single matching bean but found 2: logDataSourceProperties,spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties

Completely remove the method:

@Bean("logDataSourceProperties")
public DataSourceProperties logDataSourceProperties() {
    return new DataSourceProperties();
}

and change your:

@Bean(name = "logDataSource")
public DataSource dataSource(@Qualifier("logDataSourceProperties") DataSourceProperties properties) {
 // ...
}

to:

@Bean(name = "logDataSource")
public DataSource dataSource(DataSourceProperties properties) {
 // ...
}
Sign up to request clarification or add additional context in comments.

7 Comments

OK I did like you said, now I am getting this exception: Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
this probably means that logEntityManagerFactory() which creates the EntityManagerFactoryBuilder bean in your TestDatabaseConfig is not loaded. Can you debug your project to see if placing breakpoints there work? Else try to change @ContextConfiguration(classes = {TestConfig.class}) with @ContextConfiguration(classes = {TestDatabaseConfig.class})
I added a breakpoint there but I have no clue of what is failing... It prints NoSuchBeanDefinitionException etc. without more information, even in DEBUG.
So..it doesn't stop to the breakpoint? Just to make sure, place your breakpoint at line: return builder.dataSource(logDataSource)
Does it stop at any breakpoint inside TestDatabaseConfig? This means that your config class is not seen at all which is strange since it is declared in @ContextConfiguration(classes = {TestDatabaseConfig.class})
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.