DarthRoman DarthRoman - 25 days ago 29
Java Question

Springboot: How can I perform an integration test with real dependencies?

I'm starting to learn both Java and Spring boot now, and I'm having some problems with dependency injection in integration tests. I have a class under src/main/java/com/rfd/domain/services called TransactionService, which is marked as @Service and which has another dependencies, one of them a repository created by Spring boot. When I launch the application, it is launched correctly so I assume the dependencies are being resolved correctly. This is the summarized class:

package com.rfd.domain.services;

import allNeededImports

@Service
public class TransactionsService {

@Autowired
private KambiTransactionRepository kambiTransactionRepository;

@Autowired
private TransactionFactory transactionFactory;

public List<Transaction> retrieveTransactions(String couponExternalId) throws InvalidTransactionException {
// someCode
}
}


and now, I have a TransactionsServiceTests class under /src/test/java/com/rfd/integrationtests/domain/services:

package com.rfd.integrationtests.domain.services;
import allNeededImports

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Main.class)
@DataMongoTest
@TestPropertySource(locations = "classpath:application-integrationtest.properties")
public class TransactionsServiceTests {

@Autowired
private TransactionsService transactionsService;

@Test
public void retrieveTransactions_happyPathMultipleTransactions_transactionsRetrieved() throws InvalidTransactionException {
// test code
}


When I try to launch the tests, I receive the following error:


Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'com.rfd.domain.services.TransactionsService'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}


I have tried to create my own @TestConfiguration class, in which I create a method marked with @Bean and returning a new instance of TransactionService, and it works. However, the error now is for the KambiTransactionRepository dependency, and I don't have an implementation of it because it is given by spring boot:

package com.rfd.infrastructure.repositories;

import com.rfd.infrastructure.models.KambiTransaction;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface KambiTransactionRepository extends MongoRepository<KambiTransaction, String> {

List<KambiTransaction> findByCouponRef(String couponRef);
}


QUESTION
How can I execute the integration test using the dependency resolution of the main code?

Answer Source

As @M.Deinum remarked in comments, @SpringBootTest and @DataMongoTest are mutually exclusive, so removing @DataMongoTest solved the problem.

However, if you still want to use the @DataMongoTest annotation, you can use this sentence:

@DataMongoTest(includeFilters = @ComponentScan.Filter(Service.class))

That way, all classes tagget with annotation @Service will be loadad and autowired. Same with @Component, @Repository or @Controller