Spring Boot:如何使用真正的依赖项执行集成测试?
Springboot: How can I perform an integration test with real dependencies?
我现在开始学习 Java 和 Spring 启动,我在集成测试中遇到了一些依赖注入问题。我在 src/main/java/com/rfd/domain/services 下有一个名为 TransactionService 的 class,它被标记为 @Service 并且它有另一个依赖项,一个其中一个由 Spring boot 创建的存储库。当我启动应用程序时,它会正确启动,因此我假设依赖项已正确解析。这是总结 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
}
}
现在,我在 /src/test/java/com/rfd/integrationtests/domain/services:
下有一个 TransactionsServiceTests class
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
}
当我尝试启动测试时,收到以下错误:
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)}
我尝试创建自己的@TestConfiguration class,我在其中创建了一个标有@Bean 的方法并返回了一个新的TransactionService 实例,并且它有效。但是,现在的错误是针对 KambiTransactionRepository 依赖项,我没有它的实现,因为它是由 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);
}
问题
如何使用主代码的依赖解析来执行集成测试?
正如@M.Deinum 在评论中所说,@SpringBootTest
和 @DataMongoTest
是互斥的,因此删除 @DataMongoTest
解决了问题。
不过,如果你还想用@DataMongoTest
注解,可以用这句话:
@DataMongoTest(includeFilters = @ComponentScan.Filter(Service.class))
这样,所有用 @Component
注释的 类 都将被加载并自动装配。这包括(除其他外)@Service
、@Repository
和 @Controller
.
我需要为我的存储服务添加测试,我需要自动装配 MongoRepository
。这个问题的答案并没有解决我的问题。但是我找到了一个解决方案并将在这里分享以防其他人需要。我按如下方式解决了它:
存储库:
@Repository
public interface MyRepository extends MongoRepository<MyEntity, String> {
}
实体:
@Document(collection = "my_entity")
public class MyEntity {
@Id
private String id;
}
服务:
@Service
public class StorageServiceImpl implements StorageService {
private final MyRepository repository;
public StorageServiceImpl(MyRepository repository) {
this.repository = repository;
}
...
}
测试:
@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());
}
...
}
测试配置:
@TestConfiguration
public class ObjectMapperConfiguration {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
测试应用程序
@SpringBootApplication
public class TestApplication {
}
我现在开始学习 Java 和 Spring 启动,我在集成测试中遇到了一些依赖注入问题。我在 src/main/java/com/rfd/domain/services 下有一个名为 TransactionService 的 class,它被标记为 @Service 并且它有另一个依赖项,一个其中一个由 Spring boot 创建的存储库。当我启动应用程序时,它会正确启动,因此我假设依赖项已正确解析。这是总结 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
}
}
现在,我在 /src/test/java/com/rfd/integrationtests/domain/services:
下有一个 TransactionsServiceTests classpackage 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
}
当我尝试启动测试时,收到以下错误:
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)}
我尝试创建自己的@TestConfiguration class,我在其中创建了一个标有@Bean 的方法并返回了一个新的TransactionService 实例,并且它有效。但是,现在的错误是针对 KambiTransactionRepository 依赖项,我没有它的实现,因为它是由 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);
}
问题 如何使用主代码的依赖解析来执行集成测试?
正如@M.Deinum 在评论中所说,@SpringBootTest
和 @DataMongoTest
是互斥的,因此删除 @DataMongoTest
解决了问题。
不过,如果你还想用@DataMongoTest
注解,可以用这句话:
@DataMongoTest(includeFilters = @ComponentScan.Filter(Service.class))
这样,所有用 @Component
注释的 类 都将被加载并自动装配。这包括(除其他外)@Service
、@Repository
和 @Controller
.
我需要为我的存储服务添加测试,我需要自动装配 MongoRepository
。这个问题的答案并没有解决我的问题。但是我找到了一个解决方案并将在这里分享以防其他人需要。我按如下方式解决了它:
存储库:
@Repository
public interface MyRepository extends MongoRepository<MyEntity, String> {
}
实体:
@Document(collection = "my_entity")
public class MyEntity {
@Id
private String id;
}
服务:
@Service
public class StorageServiceImpl implements StorageService {
private final MyRepository repository;
public StorageServiceImpl(MyRepository repository) {
this.repository = repository;
}
...
}
测试:
@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());
}
...
}
测试配置:
@TestConfiguration
public class ObjectMapperConfiguration {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
测试应用程序
@SpringBootApplication
public class TestApplication {
}