Java Spring Boot Test:如何从测试上下文中排除java配置类

Ser*_*gey 13 java testing spring spring-boot

我有一个带有弹簧启动的Java Web应用程序

运行测试时我需要排除一些Java配置文件:

测试配置(测试运行时需要包含):

@TestConfiguration
@PropertySource("classpath:otp-test.properties")
public class TestOTPConfig { }
Run Code Online (Sandbox Code Playgroud)

生产配置(测试运行时需要排除):

 @Configuration
 @PropertySource("classpath:otp.properties")
 public class OTPConfig { }
Run Code Online (Sandbox Code Playgroud)

测试类(使用显式配置类):

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestAMCApplicationConfig.class)
public class AuthUserServiceTest { .... }
Run Code Online (Sandbox Code Playgroud)

测试配置:

@TestConfiguration
@Import({ TestDataSourceConfig.class, TestMailConfiguration.class, TestOTPConfig.class })
@TestPropertySource("classpath:amc-test.properties")
public class TestAMCApplicationConfig extends AMCApplicationConfig { }
Run Code Online (Sandbox Code Playgroud)

也有课:

@SpringBootApplication
public class AMCApplication { }
Run Code Online (Sandbox Code Playgroud)

当测试运行时OTPConfig,我需要TestOTPConfig...

我该怎么做?

小智 12

通常,您可以使用Spring配置文件来包含或排除Spring bean,具体取决于哪个配置文件处于活动状态.在您的情况下,您可以定义生产配置文件,默认情况下可以启用; 和测试配置文件.在生产配置类中,您将指定生产配置文件:

@Configuration
@PropertySource("classpath:otp.properties")
@Profile({ "production" })
public class OTPConfig {
}
Run Code Online (Sandbox Code Playgroud)

测试配置类将指定测试配置文件:

@TestConfiguration
@Import({ TestDataSourceConfig.class, TestMailConfiguration.class,    TestOTPConfig.class })
@TestPropertySource("classpath:amc-test.properties")
@Profile({ "test" })
public class TestAMCApplicationConfig extends AMCApplicationConfig {
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的测试类中,您应该能够说出哪些配置文件处于活动状态:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestAMCApplicationConfig.class)
@ActiveProfiles({ "test" })
public class AuthUserServiceTest {
  ....
}
Run Code Online (Sandbox Code Playgroud)

在生产中运行项目时,您可以通过设置环境变量将"production"包含为默认活动配置文件:

JAVA_OPTS="-Dspring.profiles.active=production"
Run Code Online (Sandbox Code Playgroud)

当然,您的生产启动脚本可能会使用除JAVA_OPTS之外的其他内容来设置Java环境变量,但不知何故应该设置spring.profiles.active.


Ond*_*zek 11

你也可以@ConditionalOnProperty像下面这样使用:

@ConditionalOnProperty(value="otpConfig", havingValue="production")
@Configuration
@PropertySource("classpath:otp.properties")
public class OTPConfig { }
Run Code Online (Sandbox Code Playgroud)

和测试:

@ConditionalOnProperty(value="otpConfig", havingValue="test")
@Configuration
@PropertySource("classpath:otp-test.properties")
public class TestOTPConfig { }
Run Code Online (Sandbox Code Playgroud)

然后在你的 main/resources/config/application.yml

otpConfig: production
Run Code Online (Sandbox Code Playgroud)

并且在你的 test/resources/config/application.yml

otpConfig: test
Run Code Online (Sandbox Code Playgroud)

  • 将环境特定的字符串放入源代码中很尴尬。我有时看到它,总是刺痛我的眼睛。关注点分离:使用它来修复测试是个坏主意(!)。 (4认同)

Mat*_*ntz 8

在test 文件夹中创建与“无用”镜像相同的类,例如:

src中你有/app/MyConfig.java

使用@Configuration测试文件夹中创建/app/MyConfig.java并在其中保留空主体。


Ani*_*wat 7

此外,为了排除自动配置:

@EnableAutoConfiguration(exclude=CassandraDataAutoConfiguration.class)
public class // ...
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于@SpringBootTest (2认同)

Ric*_*Art 6

您也可以模拟不需要的配置。例如:

@MockBean
private AnyConfiguration conf;
Run Code Online (Sandbox Code Playgroud)

把它放到你的测试类中。这应该有助于避免AnyConfiguration正在加载真实。

  • `@SpringBootTest` 将扫描并加载 `@Configuration` ,然后才会生效...... (8认同)
  • 这看起来像是随机行为。在我的笔记本电脑环境中,@MockBean 覆盖了原始 bean。在我们的CI环境中,原来的bean正在运行。找不到环境之间的任何相关差异,代码相同并且活动配置文件相同。 (3认同)

yno*_*tu. 6

在测试期间设置配置文件,并OTPConfig仅在配置文件未激活时加载。

@Profile("!test")
@Configuration
class OTPConfig { ... }

@SpringBootTest(properties = ["spring.profiles.include=test"])
public class AuthUserServiceTest { .... }
Run Code Online (Sandbox Code Playgroud)

  • 测试不应影响生产代码 (2认同)