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

Posted

技术标签:

【中文标题】Java Spring Boot 测试:如何从测试上下文中排除 java 配置类【英文标题】:Java Spring Boot Test: How to exclude java configuration class from test context 【发布时间】:2017-02-05 09:15:43 【问题描述】:

我有一个带有 Spring Boot 的 Java Web 应用程序

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

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

@TestConfiguration
@PropertySource("classpath:otp-test.properties")
public class TestOTPConfig  

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

 @Configuration
 @PropertySource("classpath:otp.properties")
 public class OTPConfig  

测试类(带有显式配置类):

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestAMCApplicationConfig.class)
public class AuthUserServiceTest  .... 

测试配置:

@TestConfiguration
@Import( TestDataSourceConfig.class, TestMailConfiguration.class, TestOTPConfig.class )
@TestPropertySource("classpath:amc-test.properties")
public class TestAMCApplicationConfig extends AMCApplicationConfig  

还有类:

@SpringBootApplication
public class AMCApplication  

测试运行时使用OTPConfig,但我需要TestOTPConfig...

我该怎么做?

【问题讨论】:

请注意,为了提高开发时间和运行时间的效率,通常最好只列出您想要包含的特定配置类。 【参考方案1】:

您也可以使用@ConditionalOnProperty,如下所示:

@ConditionalOnProperty(value="otpConfig", havingValue="production")
@Configuration
@PropertySource("classpath:otp.properties")
public class OTPConfig  

对于测试:

@ConditionalOnProperty(value="otpConfig", havingValue="test")
@Configuration
@PropertySource("classpath:otp-test.properties")
public class TestOTPConfig  

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

otpConfig: production

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

otpConfig: test

【讨论】:

对于@ConditionalOnMissingProperty,请参阅here【参考方案2】:

另外,排除自动配置:

@EnableAutoConfiguration(exclude=CassandraDataAutoConfiguration.class)
public class // ...

【讨论】:

【参考方案3】:

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

@MockBean
private AnyConfiguration conf;

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

【讨论】:

@SpringBootTest 将在此之前扫描并加载@Configuration... 它看起来对某些人有效,而对某些人则无效。也许这与命名和覆盖有关? 它看起来像随机行为。在我的笔记本电脑环境中,@MockBean 覆盖了原始 bean。在我们的 CI 环境中,原始 bean 正在运行。找不到环境之间的任何相关差异,代码相同且活动配置文件相同。【参考方案4】:

我使用的最简单的方法 -

    @ConditionalOnProperty 放入我的主要源代码中。 然后定义一个测试 bean 并将其添加为测试配置的一部分。在主测试类或任何其他方式中导入该配置。这仅在您需要注册测试 bean 时才需要。如果您不需要该 bean,请转到下一步。 在 src/test/resources 下的 application.properties 中添加一个属性,以禁用主文件夹中存在的配置类。

瞧!

【讨论】:

【参考方案5】:

您可以在配置类中使用@ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringJUnit4ClassRunner")SpringJUnit4ClassRunner 可以替换为仅在测试环境中退出的任何类。

【讨论】:

可以这样做,它可能会工作,但感觉笨拙且容易出错。将来查看代码的人不会很清楚它在做什么以及为什么,这将使得他们很可能会删除它,并且由于测试可能会继续通过,他们直到很久以后才会意识到自己的错误.在生产代码中包含特定于测试的代码通常也不是一个好主意。最好让生产代码没有异常地工作,并将异常放入您的测试代码中。 是的。我非常同意你的观点。但是它很简单,给它一个评论将弥补它的可读性。但是正如您所说,“在生产代码中包含特定于测试的代码通常也不是一个好主意”,谢谢。 @DaveyDaveDave【参考方案6】:

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

@Configuration
@PropertySource("classpath:otp.properties")
@Profile( "production" )
public class OTPConfig 

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

@TestConfiguration
@Import( TestDataSourceConfig.class, TestMailConfiguration.class,    TestOTPConfig.class )
@TestPropertySource("classpath:amc-test.properties")
@Profile( "test" )
public class TestAMCApplicationConfig extends AMCApplicationConfig 

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

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestAMCApplicationConfig.class)
@ActiveProfiles( "test" )
public class AuthUserServiceTest 
  ....

当您在生产环境中运行项目时,您可以通过设置环境变量将“生产”作为默认活动配置文件:

JAVA_OPTS="-Dspring.profiles.active=production"

当然,您的生产启动脚本可能会使用除 JAVA_OPTS 之外的其他东西来设置 Java 环境变量,但您应该以某种方式设置 spring.profiles.active

【讨论】:

以上是关于Java Spring Boot 测试:如何从测试上下文中排除 java 配置类的主要内容,如果未能解决你的问题,请参考以下文章

从 Spring-Boot 测试中排除 elasticsearchTemplate

Spring Boot:测试包含 Java 时间的 ResponseEntity

java.lang.IllegalStateException:无法加载 ApplicationContext Spring Boot + JUnit 测试

在java Spring Boot中,如何在集成测试中将内存中的LDAPConnection对象传递给ldapService?

从 eclipse+gradle 运行时 Spring Boot 错误加载测试配置

从 cmd 运行时的 Spring Boot 负载测试数据库