Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure EntityManagerFactoryBuilder bean when testing Spring Boot Batch application?

I have a Spring Boot Batch application that I'm writing integration tests against. However, I'm getting the following error about the EntityManagerFactoryBuilder bean missing when running a test:

org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'entityManagerFactory' defined in com.example.DatabaseConfig: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder]: : 
No qualifying bean of type [org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. 
Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type [org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]

My understanding is that Spring Boot provides the EntityManagerFactoryBuilder bean on application startup. How can I have the EntityManagerFactoryBuilder provided when running tests?

Here's my test code:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {DatabaseConfig.class, BatchConfiguration.class})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
        StepScopeTestExecutionListener.class })

public class StepScopeTestExecutionListenerIntegrationTests {

    @Autowired
    private FlatFileItemReader<Foo> reader;

    @Rule
    public TemporaryFolder testFolder = new TemporaryFolder();

    public StepExecution getStepExection() {
        StepExecution execution = MetaDataInstanceFactory.createStepExecution();
        return execution;
    }

    @Test
    public void testGoodData() throws Exception {
       //some test code
    }

Here's the DatabaseConfig class:

@Configuration
@EnableJpaRepositories(basePackages={"com.example.repository"}, 
entityManagerFactoryRef="testEntityManagerFactory",
transactionManagerRef = "testTransactionManager")
public class DatabaseConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean testEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(dataSource())
                .packages("com.example.domain")
                .persistenceUnit("testLoad")
                .build();
    }

    @Bean
    @ConfigurationProperties(prefix="spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public PlatformTransactionManager testTransactionManager(EntityManagerFactory testEntityManagerFactory) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(testEntityManagerFactory);
        return transactionManager;
    }

}
like image 534
James Avatar asked Jan 19 '16 17:01

James


1 Answers

When (integration) testing a Spring Boot application that is what you should do. The @SpringApplicationConfiguration is intended to take your application class (the one with the @SpringBootApplication annotation) as it will then be triggered to do much of the same auto configuration as a regular Spring Boot application.

You are only including 2 configuration classes and as such no auto configuration will be done.

like image 156
M. Deinum Avatar answered Oct 14 '22 22:10

M. Deinum