在 Spring Boot 中跳过关于 *** DNS 可用性的集成测试

Posted

技术标签:

【中文标题】在 Spring Boot 中跳过关于 *** DNS 可用性的集成测试【英文标题】:Skipping integration tests in spring boot on *** DNS availability 【发布时间】:2019-11-07 10:31:25 【问题描述】:

我有一个中等繁重的 springboot 服务,启动快乐流需要 10-15 秒,重试/故障转移流需要 (1-2) 分钟失败。这对我的业务流程来说没问题,也是我期望健康服务的行为方式。

我有集成测试(在我的服务中运行一些端到端流程),只能在测试机器(或开发机器)连接到特定 *** 时测试实际集成状态。

如果我没有连接到 ***,我想自动跳过集成测试。

考虑下面的代码

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Server.class, // auto scans a bunch of components
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) // slow loading context
public class IntegrationTest 
    @BeforeClass
    public static void beforeClass() 
        Assume.assumeTrue(DnsTool.***Connected()); // fast failing test
    

    @Test
    public void testIntegration() 
        // some test logic
    

当假设通过时,我的测试就会运行,一切都很好。 当假设失败时,我的测试会被跳过,但只有在尝试加载昂贵的上下文之后。

如何避免我的测试套件运行时间过长?

我尝试过的事情:

继承SpringJUnit4ClassRunner,并覆盖isTestMethodIgnored。 添加TestExecutionListener,并在beforeTestClass 中抛出假设异常

这些对 Spring 没有任何影响,并且上下文以任何方式加载。

我没有尝试过的事情:

我认为 Lazy init 附带了 2.2.X 的下一个 Spring 稳定版本。

懒惰的初始化可能会让我的问题消失,但我觉得应该有一些我缺少的简单的 spring-test/junit 修复。

提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

对我来说,这听起来像是你根本不应该在测试中做的事情。 测试(至少恕我直言)应该检查业务案例并假设环境已设置并准备就绪。

也许值得将此功能委托给构建工具和 CI。

例子:

在 maven(或您使用的任何构建工具)中定义一个配置文件,该配置文件将运行需要 *** 的集成测试。定义将运行所有其余集成测试的配置文件。 如果某些系统属性可用,请激活配置文件。

在作为 CI 的一部分的 CI 工具(如 Jenkins)中,甚至在您运行 maven 之前,运行将检查 *** 连接的脚本。根据结果​​设置系统属性并使用这些属性运行 maven。将加载所需的配置文件并运行所有测试/仅不需要 *** 的测试。

更新

如果你需要让它从 Spring 开始工作(看起来你更喜欢这种方式), Spring有一个特殊的注解叫做@IfProfileValue

默认情况下,它与系统属性匹配,如果值不匹配,则忽略测试。

看起来像这样(请注意,您也可以将此注释放在类上,然后它将适用于类中的所有测试方法):

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTestClass 


    @IfProfileValue(name = "os.name", values = "Linux")
    @Test
    public void testMe() 
     // will run only in linux, otherwise
     // won't even try to load an 
     // application context
    ....
    
  

这涵盖了您从外部解析 *** 连接并使用属性运行测试的情况。但是,如果你想在 java 中实现 *** 连接检查,这个注解是不够的,因为它只能与 Java 系统属性一起使用,所以为了使用自定义逻辑,你需要实现 org.springframework.test.annotation.ProfileValueSource

public class ***ConnectivityProfileValueSource implements ProfileValueSource 

  private String ***Enabled = "true";
  public ***ConnectivityProfileValueSource () 
     // no spring context is available here
     ClassPathResource resource = new ClassPathResource("***-config.properties");

     if (resource.exists()) 
          // read the *** address, 
          //   
          //this.testProps = PropertiesLoaderUtils.loadProperties(resource);
          // invoke your utility, check the connectivity, etc. 
          this.***Enabled = ...
     



  @Override
  public String get(String key) 
    // this is important method, 
    if(key.equals("***.enabled") 
       return this.***Enabled;  
     
    else return System.getProperty(key);
  

最后一件事是让测试知道 ProfileValueSource: 为此,您在测试中添加了另一个特殊注释: @ProfileValueSourceConfiguration(***ConnectivityProfileValueSource.class)

总而言之,测试看起来像这样:

@RunWith(SpringRunner.class)
@SpringBootTest
@ProfileValueSourceConfiguration(***ConnectivityProfileValueSource.class)
@IfProfileValue(name = "***.enabled", value = "true")
public class MyTestClass 

   @Test
   public void testMe() 
     ....
   

我提到的所有类/注释都位于包org.springframework.test.annotation

【讨论】:

你基本上是说我在junit中使用了假设,比他们打算使用的要难一些。我的意思是“纯文本”我的集成测试,假设一个有效的 *** 连接。在我知道 junit 中的假设存在之前,我会完全转向 CI 解决方案。我是一个被宠坏的开发人员,我想要一个解决方案JAVA 当测试运行时(即使它没有加载应用程序竞赛)它会提供某种报告来确保以后影响构建结果......那么如果没有启用 *** 怎么办,测试地位真的体现吗?只是我的想法...... 来自 juint4 的假设文档:失败的假设通常不会被记录,因为可能有许多测试不适用。在詹金斯上,我只是从我的可靠结果中获得了“跳过”测试的日志……这没关系 IMO 也许你可以在Server.class上设置一个条件注释呢?这样应用上下文会加载得更快,因为它实际上不会扫描任何东西? 嘿,我已经用 Java/Spring 解决方案更新了答案。请查看

以上是关于在 Spring Boot 中跳过关于 *** DNS 可用性的集成测试的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spring-mvc 中跳过杰克逊时区校正?

仅在 node_modules 中跳过库检查

spring cloud gateway 某些路由中跳过全局过滤器

如果在 Spring Data JPA 中为空或为空,如何在 @Query 中跳过 @Param

在 Vim 中跳过撤消步骤

如何从mysql中的表中跳过行