如何使用 spring 引导和注释在测试 class 中正确注入 Beans
How to inject Beans inside a test class properly with spring boot and annotations
我有一个 class 我想测试当某个配置文件处于活动状态时它是否使用正确的 Bean。因此,我为 DomesticService(反过来使用 GardeningService 和 CleaningService,所有这些都是自动装配的)编写了一个测试 class,配置文件处于活动状态。
@Component
public class HumanDomesticService implements DomesticService {
private CleaningService cleaningService;
private GardeningService gardeningService;
private Logger logger;
HumanDomesticService() {
}
@Autowired
public HumanDomesticService(CleaningService cleaningService, GardeningService gardeningService, Logger logger) {
setCleaningService(cleaningService);
setGardeningService(gardeningService);
setLogger(logger);
}
我做了一个测试配置 class,它应该扫描整个项目的 Beans,因为 SpringBootApplication 注释包含 ComponentScan 注释。
@SpringBootApplication
public class ActiveProfileConfig {
}
但我的测试 class 似乎无法找到合适的 Bean 来完成测试。
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'be.mycompany.springlessons.housekeeping.domestic.service.ActiveProfileSmallHouseTest': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'be.mycompany.springlessons.housekeeping.domestic.service.DomesticService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
在那之后,我尝试在我的配置中创建 Beans class,这使我的测试成功了,但随后 Maven 抱怨发现 2 个可以在那里注入的 Beans。 Maven似乎可以通过ComponentScan看到所有的bean。
最后我结束了导入必要的 classes,这对我的测试和 Maven 都有效,但它似乎不是正确和最好的解决方案。
@SpringBootTest(classes = ActiveProfileConfig.class)
@ActiveProfiles(profiles = "smallHouse")
@Import({HumanDomesticService.class, HumanCleaningService.class, RobotCleaningService.class, HumanGardeningService.class, HedgeTrimmerFactory.class, Broom.class, VacuumCleaner.class,
Sponge.class, DisposableDuster.class, LawnMower.class, LoggerFactory.class})
public class ActiveProfileSmallHouseTest {
@Autowired
private DomesticService service;
我尝试在 Internet 上搜索另一种解决方案,发现我不是唯一遇到问题的人,但似乎没有其他解决方案有效。
ComponentScan 在测试中似乎不起作用的原因是什么 class 以及如何最好地解决这个问题?
我很长一段时间都遇到完全相同的问题。通过添加我想使用的主要配置,我能够在 Spring Boot 中解决这个问题。以及我的测试对 @SpringBootTest
注释的 类 字段的所有必需依赖项(所有 AutoWires)。
@SpringBootTest(classes = {ActiveProfile.class, HumanDomesticService.class, HumanCleaningService.class, RobotCleaningService.class, HumanGardeningService.class, HedgeTrimmerFactory.class, Broom.class, VacuumCleaner.class,
Sponge.class, DisposableDuster.class, LawnMower.class, LoggerFactory.class})
@ActiveProfiles({"smallhouse"})
public class ActiveProfileSmallHouseTest {
@Autowired
private DomesticService service;
...
}
如果您没有使用 Spring Boot。您可以使用 @ContextConfiguration
注释解决此问题。它的工作方式相同,也是 @SpringBootTest
注释的一部分。
我的主要学习来源也是这样做的:Pro Spring 5 - Iuliana Cosmina 等 - Apress(第 631 页)
我仍然不知道为什么 ComponentScan 或上下文的自动加载不起作用。但至少我知道这样我的测试总是 运行。此外,您可以 运行 仅 类 使此测试成功,而不需要为测试启动整个上下文。
我想分享我们的最终解决方案。
我们都使用 IntelliJ IDEA 作为 IDE。在此 IDE 中,我们没有指定测试不应使用模块路径。 IntelliJ 现在有一个设置,允许您 enable/disable 使用单元测试的模块路径。
在 maven 中,我们已经通过将主要的 surefire 插件配置为不使用模块路径来禁用此功能。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<useModulePath>false</useModulePath>
</configuration>
</plugin>
在我们的 IDEA 中使用此 'new' 功能,我们还必须禁用它,以便我们的测试不使用 class 路径。
我们弄清楚了,因为我们的 Maven 阶段:mvn test
运行 是否进行了测试。
现在所有的测试 运行 都可以通过 @SpringBootTest
注释顺利完成。
要在 IntelliJ 中进行设置:
- 在菜单栏中:运行 > 编辑配置
- 在左侧菜单中打开子菜单 Templates > JUnit
- 取消选中使用模块路径
旁边的复选框
- 单击应用 > 确定
从现在开始,您将运行进行的所有测试都不会使用此模块路径。
如果您已经有现有的测试。 Select他们赢得了左边的菜单,并取消选中所有他们的使用模块路径选项。
我有一个 class 我想测试当某个配置文件处于活动状态时它是否使用正确的 Bean。因此,我为 DomesticService(反过来使用 GardeningService 和 CleaningService,所有这些都是自动装配的)编写了一个测试 class,配置文件处于活动状态。
@Component
public class HumanDomesticService implements DomesticService {
private CleaningService cleaningService;
private GardeningService gardeningService;
private Logger logger;
HumanDomesticService() {
}
@Autowired
public HumanDomesticService(CleaningService cleaningService, GardeningService gardeningService, Logger logger) {
setCleaningService(cleaningService);
setGardeningService(gardeningService);
setLogger(logger);
}
我做了一个测试配置 class,它应该扫描整个项目的 Beans,因为 SpringBootApplication 注释包含 ComponentScan 注释。
@SpringBootApplication
public class ActiveProfileConfig {
}
但我的测试 class 似乎无法找到合适的 Bean 来完成测试。
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'be.mycompany.springlessons.housekeeping.domestic.service.ActiveProfileSmallHouseTest': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'be.mycompany.springlessons.housekeeping.domestic.service.DomesticService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
在那之后,我尝试在我的配置中创建 Beans class,这使我的测试成功了,但随后 Maven 抱怨发现 2 个可以在那里注入的 Beans。 Maven似乎可以通过ComponentScan看到所有的bean。
最后我结束了导入必要的 classes,这对我的测试和 Maven 都有效,但它似乎不是正确和最好的解决方案。
@SpringBootTest(classes = ActiveProfileConfig.class)
@ActiveProfiles(profiles = "smallHouse")
@Import({HumanDomesticService.class, HumanCleaningService.class, RobotCleaningService.class, HumanGardeningService.class, HedgeTrimmerFactory.class, Broom.class, VacuumCleaner.class,
Sponge.class, DisposableDuster.class, LawnMower.class, LoggerFactory.class})
public class ActiveProfileSmallHouseTest {
@Autowired
private DomesticService service;
我尝试在 Internet 上搜索另一种解决方案,发现我不是唯一遇到问题的人,但似乎没有其他解决方案有效。
ComponentScan 在测试中似乎不起作用的原因是什么 class 以及如何最好地解决这个问题?
我很长一段时间都遇到完全相同的问题。通过添加我想使用的主要配置,我能够在 Spring Boot 中解决这个问题。以及我的测试对 @SpringBootTest
注释的 类 字段的所有必需依赖项(所有 AutoWires)。
@SpringBootTest(classes = {ActiveProfile.class, HumanDomesticService.class, HumanCleaningService.class, RobotCleaningService.class, HumanGardeningService.class, HedgeTrimmerFactory.class, Broom.class, VacuumCleaner.class,
Sponge.class, DisposableDuster.class, LawnMower.class, LoggerFactory.class})
@ActiveProfiles({"smallhouse"})
public class ActiveProfileSmallHouseTest {
@Autowired
private DomesticService service;
...
}
如果您没有使用 Spring Boot。您可以使用 @ContextConfiguration
注释解决此问题。它的工作方式相同,也是 @SpringBootTest
注释的一部分。
我的主要学习来源也是这样做的:Pro Spring 5 - Iuliana Cosmina 等 - Apress(第 631 页)
我仍然不知道为什么 ComponentScan 或上下文的自动加载不起作用。但至少我知道这样我的测试总是 运行。此外,您可以 运行 仅 类 使此测试成功,而不需要为测试启动整个上下文。
我想分享我们的最终解决方案。
我们都使用 IntelliJ IDEA 作为 IDE。在此 IDE 中,我们没有指定测试不应使用模块路径。 IntelliJ 现在有一个设置,允许您 enable/disable 使用单元测试的模块路径。
在 maven 中,我们已经通过将主要的 surefire 插件配置为不使用模块路径来禁用此功能。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<useModulePath>false</useModulePath>
</configuration>
</plugin>
在我们的 IDEA 中使用此 'new' 功能,我们还必须禁用它,以便我们的测试不使用 class 路径。
我们弄清楚了,因为我们的 Maven 阶段:mvn test
运行 是否进行了测试。
现在所有的测试 运行 都可以通过 @SpringBootTest
注释顺利完成。
要在 IntelliJ 中进行设置:
- 在菜单栏中:运行 > 编辑配置
- 在左侧菜单中打开子菜单 Templates > JUnit
- 取消选中使用模块路径 旁边的复选框
- 单击应用 > 确定
从现在开始,您将运行进行的所有测试都不会使用此模块路径。 如果您已经有现有的测试。 Select他们赢得了左边的菜单,并取消选中所有他们的使用模块路径选项。