如何有条件地不在 spring 引导中创建 bean?
how to conditionally not create beans in spring boot?
在我的应用程序中,我有一个组件在应用程序启动时从其他系统读取数据。
但是,在测试期间,我不希望创建此组件
@Component
@Slf4j
public class DeviceStatisticsSyncHandler {
@EventListener
public void handle(ApplicationReadyEvent event) {
syncDeviceStatisticsDataSync();
}
@Value("${test.mode:false}")
public boolean serviceEnabled;
}
我可以用condition来解决这个问题,但是其他代码读者需要理解,所以我认为这不是一个很好的方法:
@EventListener(condition = "@deviceStatisticsSyncHandler .isServiceEnabled()")
public void handle(ApplicationReadyEvent event) {
syncDeviceStatisticsDataSync();
}
public boolean isServiceEnabled() {
return !serviceEnabled;
}
@Value("${test.mode:false}")
public boolean serviceEnabled;
我的应用程序没有使用配置文件,有没有其他方法可以解决这个问题。
Spring开机version:2.1.3
如果您处于测试模式,一个可能的选择是根本不加载 DeviceStaticsticsSyncHandler
。
"test.mode" 在这里不是一个好名字,因为生产代码包含一些与测试紧密绑定的东西。
下面的方法怎么样:
@Component
@ConditionalOnProperty(name ="device.stats.handler.enabled", havingValue = "true", matchIfMissing=true)
public class DeviceStatisticsSyncHandler {
// do whatever you need here, but there is no need for "test.mode" enabled related code here
}
现在在测试中,您可以在测试本身上定义测试 属性 "device.stats.handler.enabled=false",甚至可以将该定义放在 src/test/reources/application.properties
中,这样所有测试都将是 false
在模块中。
一个明显的优点是这个定义几乎是不言自明的,其他项目维护者也很容易理解。
对我来说,这不是条件而是与环境有关的情况。我将使用 spring 配置文件解决这个问题。
步骤 1:首先创建接口
public interface DeviceStatisticsSyncHandler {
public void handle(ApplicationReadyEvent event);
}
步骤 2:为生产创建实施
@Component
@Profile("!test")
public class DeviceStatisticsSyncHandlerImpl implements DeviceStatisticsSyncHandler {
@EventListener
@Override
public void handle(ApplicationReadyEvent event) {
syncDeviceStatisticsDataSync();
}
}
步骤 3: 创建测试的实现
@Component
@Profile("test")
public class DeviceStatisticsSyncHandlerTestImpl implements DeviceStatisticsSyncHandler {
@EventListener
@Override
public void handle(ApplicationReadyEvent event) {
//do Nothing
}
}
最后一步
您需要做的就是 set/toggle 属性
-Dspring.profiles.active=test
或
-Dspring.profiles.active=prod
我找到了一种无需任何其他外部配置即可实现此目的的方法。
这个想法是创建一个适用于所有集成测试的通用配置,并在那里使用 @MockBean
来替换真正的 bean。因此,应该在 test
class 路径下创建一个像这样的 class(即在正常应用程序启动期间不扫描):
@Configuration
public class IntegrationTestConfiguration
{
@MockBean
public DeviceStatisticsSyncHandler deviceStatisticsSyncHandler;
}
我真的很惊讶 @MockBean
可以在这里使用,但 Javadoc 明确指出:Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner.
.
在我的应用程序中,我有一个组件在应用程序启动时从其他系统读取数据。 但是,在测试期间,我不希望创建此组件
@Component
@Slf4j
public class DeviceStatisticsSyncHandler {
@EventListener
public void handle(ApplicationReadyEvent event) {
syncDeviceStatisticsDataSync();
}
@Value("${test.mode:false}")
public boolean serviceEnabled;
}
我可以用condition来解决这个问题,但是其他代码读者需要理解,所以我认为这不是一个很好的方法:
@EventListener(condition = "@deviceStatisticsSyncHandler .isServiceEnabled()")
public void handle(ApplicationReadyEvent event) {
syncDeviceStatisticsDataSync();
}
public boolean isServiceEnabled() {
return !serviceEnabled;
}
@Value("${test.mode:false}")
public boolean serviceEnabled;
我的应用程序没有使用配置文件,有没有其他方法可以解决这个问题。
Spring开机version:2.1.3
如果您处于测试模式,一个可能的选择是根本不加载 DeviceStaticsticsSyncHandler
。
"test.mode" 在这里不是一个好名字,因为生产代码包含一些与测试紧密绑定的东西。
下面的方法怎么样:
@Component
@ConditionalOnProperty(name ="device.stats.handler.enabled", havingValue = "true", matchIfMissing=true)
public class DeviceStatisticsSyncHandler {
// do whatever you need here, but there is no need for "test.mode" enabled related code here
}
现在在测试中,您可以在测试本身上定义测试 属性 "device.stats.handler.enabled=false",甚至可以将该定义放在 src/test/reources/application.properties
中,这样所有测试都将是 false
在模块中。
一个明显的优点是这个定义几乎是不言自明的,其他项目维护者也很容易理解。
对我来说,这不是条件而是与环境有关的情况。我将使用 spring 配置文件解决这个问题。
步骤 1:首先创建接口
public interface DeviceStatisticsSyncHandler {
public void handle(ApplicationReadyEvent event);
}
步骤 2:为生产创建实施
@Component
@Profile("!test")
public class DeviceStatisticsSyncHandlerImpl implements DeviceStatisticsSyncHandler {
@EventListener
@Override
public void handle(ApplicationReadyEvent event) {
syncDeviceStatisticsDataSync();
}
}
步骤 3: 创建测试的实现
@Component
@Profile("test")
public class DeviceStatisticsSyncHandlerTestImpl implements DeviceStatisticsSyncHandler {
@EventListener
@Override
public void handle(ApplicationReadyEvent event) {
//do Nothing
}
}
最后一步
您需要做的就是 set/toggle 属性
-Dspring.profiles.active=test
或
-Dspring.profiles.active=prod
我找到了一种无需任何其他外部配置即可实现此目的的方法。
这个想法是创建一个适用于所有集成测试的通用配置,并在那里使用 @MockBean
来替换真正的 bean。因此,应该在 test
class 路径下创建一个像这样的 class(即在正常应用程序启动期间不扫描):
@Configuration
public class IntegrationTestConfiguration
{
@MockBean
public DeviceStatisticsSyncHandler deviceStatisticsSyncHandler;
}
我真的很惊讶 @MockBean
可以在这里使用,但 Javadoc 明确指出:Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner.
.