9

Confident this hasn't been asked but reading through the Spring docs and testing utilities I found this annotation and thought I'd start using it. Reading through the fine print I read:

Regular @Component beans will not be loaded into the ApplicationContext.

That sounded good and I even liked the idea of using H2 except from what I found the entity I wanted to use had catalog and schema modifiers to it and the default H2 I couldn't figure out how to support that. I made an H2 datasource for the test branch and use that and override the replace. I wound up with

@RunWith(SpringRunner.class)
@ContextConfiguration(classes=ABCH2Congfiguration.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
public class StatusRepositoryTest {

}

However my tests fails fro Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type. which leads to: Error creating bean with name 'customerServiceImpl': Unsatisfied dependency.

However the customerServiceImpl is this bean:

@Component
public class CustomerServiceImpl  implements CustomerService {
}

That says @Component. The fine print for DataJpaTest says it doesn't load @Components. Why is it doing that and thus failing the test?

As Kyle and Eugene asked below here's the rest:

package com.xxx.abc.triage;
@Component
public interface CustomerService {
}

Configuration
@ComponentScan("com.xxx.abc")
@EnableJpaRepositories("com.xxx.abc")
//@Profile("h2")
public class ABMH2Congfiguration {

    @Primary
    @Bean(name = "h2source")
    public DataSource dataSource() {
        EmbeddedDatabase build = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).setName("ABC").addScript("init.sql").build();
        return build;
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter bean = new HibernateJpaVendorAdapter();
        bean.setDatabase(Database.H2);
        bean.setShowSql(true);
        bean.setGenerateDdl(true);
        return bean;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(dataSource);
        bean.setJpaVendorAdapter(jpaVendorAdapter);
        bean.setPackagesToScan("com.xxx.abc");
        return bean;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }

}

And just to clarify the question, why is @Component being loaded into the context within a @DataJpaTest?

Michael Sampson
  • 369
  • 1
  • 6
  • 19

2 Answers2

1

@ComponentScan automatically inject all found @Component and @Service into context. You could override it by separate @Bean:

@Bean
CustomerService customerService{
    return null;
}

Or remove @Component annotation from CustomerService and CustomerServiceImpl, but you should add @Bean at your production @Configuration

Eugene Ustimenko
  • 322
  • 4
  • 16
1

@DataJpaTest does not load @Component, @Service... by default, only @Repository and internal things needed to configure Spring data JPA.

In your test, you can load any @Configuration you need, and in your case, you load @ABMH2Congfiguration which performs a @ComponentScan that's why Spring try to load your CustomerService.

You should only scanning the @Repository in this configuration class, and scan others @Component, @Service... in another @Configuration like DomainConfiguration. It's always a good practice to separate different types of configurations.

Farid Mesnata
  • 224
  • 4
  • 6