5
votes

I am working on a spring boot based webservice with following structure:

Controller (REST) --> Services --> Repositories (as suggested in some tutorials).

My Database Connection (JPA/Hibernate/MySQL) is defined in a @Configuration class. (see below)

Now I'd like to write simple tests for methods in my Service classes, but I don't really understand how to load ApplicationContext into my test classes and how to mock the JPA / Repositories.

This is how far I came:

My service class

@Component
public class SessionService {
    @Autowired
    private SessionRepository sessionRepository;
    public void MethodIWantToTest(int i){
    };
    [...]
}

My test class:

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

    @Configuration
    static class ContextConfiguration {
        @Bean
        public SessionService sessionService() {
            return new SessionService();
        }
    }

    @Autowired
    SessionService sessionService;
    @Test
    public void testMethod(){
    [...]
  }
}

But I get following exception:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.myApp.SessionRepository com.myApp.SessionService.sessionRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.myApp.SessionRepository] 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)}

For completeness: here's my @Configuration for jpa:

@Configuration
@EnableJpaRepositories(basePackages={"com.myApp.repositories"})
@EnableTransactionManagement
public class JpaConfig {


    @Bean
    public ComboPooledDataSource dataSource() throws PropertyVetoException, IOException {
        ...
    }

   @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
        ...
    }


    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        ...
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
   ...
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
  ... 
   }
}
2

2 Answers

2
votes

use @SpringBootTest and @RunWith(SpringRunner.class) to load the context

@RunWith(SpringRunner.class)
@SpringBootTest
class Demo{
    @Test
    void contextLoad(){}
}
0
votes

In your test Spring will use configuration only from inner ContextConfiguration class. This class describes your context. In this context you created only service bean and no repository. So the only bean that will be created is SessionService. You should add description of SessionRepository in inner ContextConfiguration. Your JpaConfig class will not be used in test class(you don't specify this), only in application.