在春季启动中跳过关于VPN DNS可用性的集成测试

时间:2019-06-25 14:36:54

标签: java spring-boot junit integration-testing junit4

我有一个比较沉重的springboot服务,要启动一个愉快的流需要10到15秒,而在重试/故障转移流上要花费(1-2)分钟才能失败。这对我的业务流程来说是可以的,也是我期望健康的服务表现的方式。

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

如果我未连接到VPN,我想自动跳过集成测试。

考虑以下代码

@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.vpnConnected()); // fast failing test
    }

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

当这些假设通过时,我的测试就会开始,一切都很好。 当假设失败时,我的测试将被跳过,但是只有在尝试加载昂贵的上下文之后才可以。

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

我尝试过的事情:

  • 子类化SpringJUnit4ClassRunner,并覆盖isTestMethodIgnored
  • 添加一个TestExecutionListener,并在beforeTestClass中抛出假设异常

这些在Spring上没有留下任何印象,并且上下文以任何方式加载。

我没有尝试的事情:

  • 我认为2.2.X的下一个稳定发行版是懒惰的init。

惰性启动可能使我的问题消失,但是我觉得应该缺少一些简单的弹簧测试/ junit修复程序。

预先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

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

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

示例:

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

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

更新

如果您需要从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
    ....
    }
  }

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

public class VPNConnectivityProfileValueSource implements ProfileValueSource {

  private String vpnEnabled = "true";
  public VPNConnectivityProfileValueSource () {
     // no spring context is available here
     ClassPathResource resource = new ClassPathResource("vpn-config.properties");

     if (resource.exists()) {
          // read the VPN address, 
          //   
          //this.testProps = PropertiesLoaderUtils.loadProperties(resource);
          // invoke your utility, check the connectivity, etc. 
          this.vpnEnabled = ...
     }

}

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

最后一件事是使测试了解ProfileValueSource: 为此,您还要在测试中添加另一个特殊注释: @ProfileValueSourceConfiguration(VPNConnectivityProfileValueSource.class)

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

@RunWith(SpringRunner.class)
@SpringBootTest
@ProfileValueSourceConfiguration(VPNConnectivityProfileValueSource.class)
@IfProfileValue(name = "vpn.enabled", value = "true")
public class MyTestClass {

   @Test
   public void testMe() {
     ....
   }
}

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