Java – Unit testing a Spring Boot service class with(out) repository in JUnit

javajunitspringspring-boot

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(){
  ... 
   }
}

Best Answer

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

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