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?
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 that are annotated with @Component
will be loaded and autowired. This includes (among others) @Service
, @Repository
and @Controller
.
I needed to add test for my storage service and I needed to autowire MongoRepository
. The answer to this question did not solve my problem. However I found a solution and will share here in case someone else needs. I solved it as following:
Repository:
@Repository
public interface MyRepository extends MongoRepository<MyEntity, String> {
}
Entity:
@Document(collection = "my_entity")
public class MyEntity {
@Id
private String id;
}
Service:
@Service
public class StorageServiceImpl implements StorageService {
private final MyRepository repository;
public StorageServiceImpl(MyRepository repository) {
this.repository = repository;
}
...
}
Test:
@Import(ObjectMapperConfiguration.class)
@DataMongoTest
class StorageServiceImplTest {
@Autowired
private MyRepository repository;
private StorageService storageService;
@BeforeEach
void setup() {
storageService = new StorageServiceImpl(repository);
var entity = new MyEntity();
repository.save(entity);
}
@Test
void create() {
assertEquals(1, repository.count());
var entity = storageService.create();
assertEquals(2, repository.count());
}
...
}
Test Config:
@TestConfiguration
public class ObjectMapperConfiguration {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
Test Application
@SpringBootApplication
public class TestApplication {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With