公司企业网站建设目的,桂林网站建设动服卖照明电源设,wordpress 加速,建设银行网上银行网站进入不了如果您或多或少有经验的Spring Boot用户#xff0c;那么很幸运#xff0c;在某些时候您可能需要遇到必须有条件地注入特定bean或配置的情况 。 它的机制是很好理解的 #xff0c;但有时这样的测试条件下#xff08;以及它们的组合#xff09;可能会导致混乱。 在这篇文章中… 如果您或多或少有经验的Spring Boot用户那么很幸运在某些时候您可能需要遇到必须有条件地注入特定bean或配置的情况 。 它的机制是很好理解的 但有时这样的测试条件下以及它们的组合可能会导致混乱。 在这篇文章中我们将讨论一些可行的方法可以说是理智的。 由于Spring Boot 1.5.x仍被广泛使用不过它将在8月向EOL迈进因此我们会将其与Spring Boot 2.1.x一起包括在JUnit 4.x和JUnit 5.x中 。 我们将要介绍的技术同样适用于常规配置类和自动配置类。 我们将使用的示例与我们的自制日志记录有关。 让我们假设我们的Spring Boot应用程序需要一些名称为“ sample”的专用记录器bean。 但是在某些情况下必须禁用此记录器或实际上使其成为noop因此在这里属性logging.enabled就像一个kill开关。 在此示例中我们使用Slf4j和Logback 但这并不是很重要。 下面的LoggingConfiguration片段反映了这个想法。 Configuration public class LoggingConfiguration { Configuration ConditionalOnProperty (name logging.enabled , matchIfMissing true ) public static class Slf4jConfiguration { Bean Logger logger() { return LoggerFactory.getLogger( sample ); } } Bean ConditionalOnMissingBean Logger logger() { return new NOPLoggerFactory().getLogger( sample ); } } 那么我们将如何测试呢 Spring Boot 通常是Spring Framework 一直提供出色的测试脚手架支持 。 SpringBootTest和TestPropertySource批注允许使用自定义属性快速引导应用程序上下文。 但是有一个问题它们是按测试类级别而不是每种测试方法应用的。 这当然是有道理的但基本上需要您为每个条件组合创建一个测试类。 如果您仍然使用JUnit 4.x 则可能会发现一个有用的技巧该技巧利用了封闭的运行器封闭的框架。 RunWith (Enclosed. class (Enclosed. ) public class LoggingConfigurationTest { RunWith (SpringRunner. class ) SpringBootTest public static class LoggerEnabledTest { Autowired private Logger logger; Test public void loggerShouldBeSlf4j() { assertThat(logger).isInstanceOf(ch.qos.logback.classic.Logger. class ); } } RunWith (SpringRunner. class ) SpringBootTest TestPropertySource (properties logging.enabledfalse ) public static class LoggerDisabledTest { Autowired private Logger logger; Test public void loggerShouldBeNoop() { assertThat(logger).isSameAs(NOPLogger.NOP_LOGGER); } } } 您仍然可以按条件获得类但至少它们都在同一嵌套中。 使用JUnit 5.x 有些事情变得容易了但没有达到人们期望的水平。 不幸的是 Spring Boot 1.5.x本身并不支持JUnit 5.x 因此我们必须依靠spring-test-junit5社区模块提供的扩展。 这是pom.xml中的相关更改请注意 spring-boot-starter-test依赖关系图中明确排除了junit 。 dependency groupId org.springframework.boot/ groupId artifactId spring-boot-starter-test/ artifactId scope test/ scope exclusions exclusion groupId junit/ groupId artifactId junit/ artifactId / exclusion / exclusions / dependency dependency groupId com.github.sbrannen/ groupId artifactId spring-test-junit5/ artifactId version 1.5.0/ version scope test/ scope / dependency dependency groupId org.junit.jupiter/ groupId artifactId junit-jupiter-api/ artifactId version 5.5.0/ version scope test/ scope / dependency dependency groupId org.junit.jupiter/ groupId artifactId junit-jupiter-engine/ artifactId version 5.5.0/ version scope test/ scope / dependency 除了使用Nested批注来自JUnit 5.x以支持将测试作为内部类之外测试用例本身没有太大区别。 public class LoggingConfigurationTest { Nested ExtendWith (SpringExtension. class ) SpringBootTest DisplayName ( Logging is enabled, expecting Slf4j logger ) public static class LoggerEnabledTest { Autowired private Logger logger; Test public void loggerShouldBeSlf4j() { assertThat(logger).isInstanceOf(ch.qos.logback.classic.Logger. class ); } } Nested ExtendWith (SpringExtension. class ) SpringBootTest TestPropertySource (properties logging.enabledfalse ) DisplayName ( Logging is disabled, expecting NOOP logger ) public static class LoggerDisabledTest { Autowired private Logger logger; Test public void loggerShouldBeNoop() { assertThat(logger).isSameAs(NOPLogger.NOP_LOGGER); } } } 如果尝试使用Apache Maven和Maven Surefire插件从命令行运行测试则可能会惊讶地发现在构建过程中没有执行任何测试。 问题是… 排除了所有嵌套类 …因此我们需要采用另一种解决方法 。 plugin groupId org.apache.maven.plugins/ groupId artifactId maven-surefire-plugin/ artifactId version 2.22.2/ version configuration excludes exclude / / excludes / configuration / plugin 这样事情应该顺利进行。 但是关于传统的足够多的是 Spring Boot 2.1.x作为完整的游戏改变者来了。 上下文运行程序家族ApplicationContextRunner ReactiveWebApplicationContextRunner和WebApplicationContextRunner提供了一种简单明了的方法可以在每个测试方法级别上定制上下文从而使测试执行异常Swift。 public class LoggingConfigurationTest { private final ApplicationContextRunner runner new ApplicationContextRunner() .withConfiguration(UserConfigurations.of(LoggingConfiguration. class )); Test public void loggerShouldBeSlf4j() { runner .run(ctx - assertThat(ctx.getBean(Logger. class )).isInstanceOf(Logger. class ) ); } Test public void loggerShouldBeNoop() { runner .withPropertyValues( logging.enabledfalse ) .run(ctx - assertThat(ctx.getBean(Logger. class )).isSameAs(NOPLogger.NOP_LOGGER) ); } } 看起来真的很棒。 Spring Boot 2.1.x对JUnit 5.x的支持要好得多并且在即将到来的2.2版本中 发布时 JUnit 5.x将是默认引擎 不用担心仍将支持旧的JUnit 4.x 。 到目前为止切换到JUnit 5.x需要在依赖项方面进行一些工作。 dependency groupId org.springframework.boot/ groupId artifactId spring-boot-starter-test/ artifactId scope test/ scope exclusions exclusion groupId junit/ groupId artifactId junit/ artifactId / exclusion / exclusions / dependency dependency groupId org.junit.jupiter/ groupId artifactId junit-jupiter-api/ artifactId scope test/ scope / dependency dependency groupId org.junit.jupiter/ groupId artifactId junit-jupiter-engine/ artifactId scope test/ scope / dependency 作为附加步骤您可能需要使用最新的Maven Surefire插件 2.22.0或更高版本以及现成的JUnit 5.x支持。 下面的代码段说明了这一点。 plugin groupId org.apache.maven.plugins/ groupId artifactId maven-surefire-plugin/ artifactId version 2.22.2/ version / plugin 我们使用的示例配置非常幼稚许多实际应用程序最终将具有由许多条件构建而成的非常复杂的上下文。 上下文赛跑者带来的灵活性和巨大的机会 Spring Boot 2.x测试脚手架的宝贵补充只是节省大量资金请紧记它们。 完整的项目资源可在Github上找到 。 翻译自: https://www.javacodegeeks.com/2019/08/testing-spring-boot-conditionals-sane-way.html