如何使用@IfProfileValue 来测试配置文件是否处于活动状态?

How can I use @IfProfileValue to test if a Profile is active?

令人困惑的是 @IfProfileValue@Profile@ActiveProfiles 无关。 @Profile 测试配置文件是否处于活动状态,@ActiveProfiles 将其设置为活动状态,@IfProfileValue 允许您检查 Spring Environment 中的内容。唔?我会弃用所有这些并添加新的 @IfEnvironment@IfProfile@ActivateProfiles

撇开评论不谈,我如何使用 @IfProfileValue 来检测我的配置文件是否处于活动状态?我现在没有在这个项目上使用 Spring Boot。答案应该显示代码,如果配置文件被激活为 @ActiveProfiles( "test" ),我们假设我希望测试 运行。

我试过 @IfProfileValue(name = "activeProfiles", value = "test") 但似乎跳过了测试,这意味着它不匹配。我推测问题可能与 ActiveProfilesCollection.

这一事实有关

So confusingly @IfProfileValue has nothing to do with @Profile or @ActiveProfiles.

没错,我在这里详细解释了这一点:

...我假设你已经看到了,因为你昨天对我的回答发表了评论。

之所以@IfProfileValue@Profile@ActiveProfiles无关,是因为框架的进化。详情见下文。

@Profile tests to see if a profile is active, @ActiveProfiles sets them as active, and @IfProfileValue allows you to check things in Spring Environment.

这些说法并不完全正确,尤其是最后一部分。

@Profile 用于有选择地启用一个组件(例如,@Service 等),@Configuration class 或 @Bean 方法,如果一个命名的 bean 定义配置文件 在 Spring Environment 中处于活动状态 ApplicationContext。此注释与测试没有直接关系:@Profile 应该 而不是 用于测试 class.

@ActiveProfiles 用于指定在加载 ApplicationContext 进行集成测试。

@IfProfileValue 允许您检查 Spring Environment 中的内容。我不确定您为什么会这样假设,因为 none 框架中的文档说明了这一点。正如我在上述主题中所述:

请注意 @IfProfileValue 是在 Spring Framework 2.0 中引入的,long 在 bean 定义配置文件的概念之前,并且 @ActiveProfiles 首次在 Spring Framework 3.1 中引入。

在上述帖子中,我还指出了以下内容:

术语 'profile' 在考虑 @IfProfileValue 的语义时可能会产生误导。关键是要考虑 'test groups'(就像 TestNG 中的那样)而不是 'profiles'。请参阅 JavaDoc for @IfProfileValue.

中的示例

how can I use @IfProfileValue to detect whether i have a profile active?

这取决于,并且......我假设你说 bean 定义配置文件 当你说 "profile".

如果您正在使用 @ActiveProfiles 为您的测试设置 bean 定义配置文件,您目前无法使用 @IfProfileValue 来确定 bean 定义配置文件 处于活动状态,因为通过 @ActiveProfiles 配置的 bean 定义配置文件 直接在测试的 ApplicationContext 中设置,而不是作为一个 Java 系统 属性.

但是,如果您通过 spring.profiles.active 系统 属性 设置 bean 定义配置文件 ,那么 可以使用 @IfProfileValue 来确定 bean 定义配置文件 是否处于活动状态,因为实际上 @IfProfileValue使用系统属性。例如,您可以使用以下内容:

@IfProfileValue(name = "spring.profiles.active", value = "test")

I tried @IfProfileValue(name = "activeProfiles", value = "test") but that seems to have the test skipped, which means it's not matching.

那是行不通的,因为 activeProfiles 是不正确的 属性 名称。正确的系统 属性 名称是 spring.profiles.active。有关详细信息,请参阅 AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME


@IfProfileValue@ActiveProfiles 不协调这一事实是 Spring 团队的一个已知问题。请查阅以下 JIRA 问题以获取更多详细信息,如果您愿意,也可以加入讨论。

希望这能为您澄清情况!

Sam(Spring TestContext Framework 的作者)

山姆成功了。 (以及几年前被接受和回答的事实)

要补充的一件事是,如果您想将系统属性传递给您的测试,如果您使用像 gradle 这样的构建工具,让它们传播到 JVM 可能需要额外的步骤.

//build.gradle
tasks.withType(Test) {
    systemProperties System.properties
}

然后在集成测试中一切照常

//MyIntegrationTest.class
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("integration")
@IfProfileValue(name = "run.integration.tests", value = "true")
public class MyIntegrationTest {
    @Test
    public void myTest(){ ... }
}

最后,您可以使用指定的 属性 从终端执行测试。

$> ./gradlew clean test -Drun.integration.tests=true

我最喜欢 @IfProfileValue 而不是抓取 System.property 并手动检查 assumeTrue/False 的一点是没有加载 Spring 上下文(或 flyway/other您可能拥有的迁移)保持单元测试快速。

不幸的是,根据我的经验,测试对@IfProfileValue

的依赖
@Test
@IfProfileValue(name="spring.profiles.active", values={"test"})

仅当您将 spring.profiles.active 设置为 JVM 属性 时才有效,如下所示: -Dspring.profiles.active="test"

@IfProfileValue just ignores spring.profiles.active from application.properties/yml.

使用 junit5 时,可以根据活动配置文件有条件地启用测试:

@EnabledIf(expression =
   "#{environment.acceptsProfiles(T(org.springframework.core.env.Profiles).of('someprofile'))}",
   loadContext = true)
class MyTest {
   ...
}

这会检查 someprofile 是否处于活动状态,这与检查 spring.profiles.active 属性 工作事件不同(如果启用了多个配置文件)。这会检查 someprofile 是否在当前活动的配置文件中。

为了使其更具可读性,可以使用 spring meta-annotation。先定义注解

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@EnabledIf(expression =
  "#{environment.acceptsProfiles(T(org.springframework.core.env.Profiles).of('someprofile'))}",
  loadContext = true)
public @interface EnabledIfSomeProfile {
}

然后在测试中使用它 类:

@EnableIfSomeProfile
class MyTest {
 ...
}