java - 如何安全地测试需要外部 Web API 的代码

标签 java rest unit-testing junit

我即将踏上编写 Java 库来包装 Web API 的旅程,我想一路编写测试,以确保一切顺利。我使用 JUnit 已经有一段时间了,并且非常乐意将它与 PowerMockito/Mockito 等工具一起使用。然而,我担心如果 API 关闭或我无法访问它,测试可能会失败,因为我最终计划在 CI 服务器 (travis-ci) 上运行它,并希望构建测试部署过程像尽可能接近自动化。

我已经进行了相当多的谷歌搜索,不幸的是,我在这里发现的大多数问题都是关于测试程序员编写的或可以在本地设置的 API 的。我知道可以通过一些修补来复制 API 的基本功能,尽管这感觉更像是倒退而不是前进。

我目前正在脑海中起草想法,到目前为止,这感觉像是一个比较可靠的解决方案,但如果有人能够验证这一点或提供更好的解决方案,那就太好了。

TestUtil.java

public static boolean isReachable() {
    try (Socket socket = new Socket("api.host.com", 80)) {
        return true;
    } catch (Exception e) {
        return false;
    }
}

测试用例.java

@BeforeClass 
public static void testReachable() {
    Assume.assumeTrue("API was not reachable, test cannot run", TestUtil.isReachable());
}

我只是出于偏执狂,用 @BeforeClass 假设它。

但是,这并没有考虑到 HTTP 错误,只是检查端口 80 上是否正在监听某些内容。是否值得用 HEAD 请求替换?除了检查错误,老实说我不确定。我不愿意在没有确认它是最佳方式的情况下使用 HTTP,因为这个库有可能变得相当大。

编辑: 我刚刚偶然发现了 InetAddress#isReachable(),尽管根据我读到的一篇文章,它并不是最可靠的。

最佳答案

您应该区分单元测试和集成测试。

单元测试不应该依赖于网络和文件系统等基础设施。所有这些方面都应该重构,例如在单元测试期间模拟的单独类或方法中。我总是将单元测试编写为“白盒”测试,我尝试使用代码覆盖工具覆盖代码中的每个可能流程。

在您的情况下,您可以为项目中的业务逻辑编写单元测试,例如以何种顺序进行哪些 API 调用、取决于 API 调用结果的逻辑规则、可能是一些与内容相关的验证和错误处理,将您的域对象映射到远程 API 的协议(protocol)等。

这只剩下实际调用 API 的部分未经测试。为此,我将运行一个嵌入式 Web 服务器(例如 Jetty),它托管模拟版本的远程 API,提供熟响应。然后您可以编写调用此本地服务器的集成测试来检查您的网络代码及其配置。

当我使用像 Spring-WS 或 JAXB 这样的框架时,我经常跳过集成测试部分,因为这意味着要做很多工作来测试你的配置,没有真正需要测试这些框架的代码。这可能只是我懒惰,但我总是尝试权衡创建测试的工作量与预期 yield 。

当您拥有复杂的服务环境并进行大量复杂的映射、配置和路由时,情况就完全不同了。然后,您的集成测试是验证所有服务是否正确连接并相互正确通信的最佳方式。我将这些称为“黑盒”测试,您在其中根据整个系统的预期功能(例如用户故事)指定测试,而与实现细节无关。

关于java - 如何安全地测试需要外部 Web API 的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34655819/

相关文章:

c# - 如何在单元测试中实现 EF 的 FIND 方法?

java - 从 java“插入”Access 2010

Java nanoTime 没有抛出可靠的结果

python - 如何测试 functools.partial 生成预期的函数对象

c# - Cosmos DB Azure 表 API o数据身份验证 REST/C#?

javascript - ($根作用域 :inprog) $apply already in progress

scala - 在 scala 测试模块中使用 gradle 运行特定测试

c# - 从 Visual Studio 迁移到 NetBeans 或其他一些 IDE

java - 如何告诉 BufferedReader 停止从 System.in 读取?

java - 将多个参数传递给rest API - Spring