ap框架_Java开发人员如何使用Wiremock框架来模拟基于HTTP的API

ap框架

重要要点

  • Wiremock网络模拟框架是节省时间的强大工具,可用于创建双线测试双打。
  • 在JUnit测试中使用Wiremock可以轻松编写快乐路径和替代路径示例的代码。
  • 我们将介绍一个独立的Wiremock使用示例
  • 我们还将介绍较少的技术测试人员可以使用UI。
  • 还讨论了替代方案。

简介:我对无线存根和模拟的经验

在我的职业生涯中,我很高兴在一系列大型公司工作,在那里我观察到了一种反复出现的发展模式:团队一次又一次地编写相同的工具。 我没有看到在两个不同的银行内部(不同的代码库)开发的三个在线HTTP存根/模拟( 有时也称为服务虚拟化工具 )。 我在一家媒体公司的同一层中看到了五个不同团队的成员,在一家航空业企业中看到了至少一个。

这些HTTP存根的外观和职责也有一种模式,主要应用于两个用例:

  1. 在自动化测试中,有一个接口可用于从JUnit测试中远程添加测试双精度测试,从而使开发人员能够在TeamCity或Jenkins等CI(连续集成)环境中运行构建。
  2. 在某些情况下,这些工具还具有Web界面,允许较少的技术测试人员进行手动探索性测试。

由于同一工具同时用于自动和手动探索性测试,因此发生了很多存根重用。 测试人员将使用开发人员创建的存根,这有助于促进它们之间的通信。 这也有助于减少用于开发双倍测试的总工作量,因为与开发人员和测试人员将使用不同解决方案的情况相比,重复次数更少。 由于团队中没有测试人员,因此某些团队只需要编程API且不需要Web界面。

行业使用现成的工具

让我们从日志记录和数据存储的更广泛的行业角度来看待这种综合症。

如果确实愿意,则可以在不超过一两天的时间内轻松实现自己的简单日志记录框架。 但是传统的观念使我们永远不能从头开始编写日志框架。 相反,我们使用Logback,Slf4J或类似的现成日志框架。

这是用于记录的相对简单的功能; 如果增加问题的复杂性,例如考虑数据存储,则几乎可以肯定的是,您将使用市场上现成的框架之一,例如Oracle,MongoDB或Neo4J,具体取决于您的情况。要求。

或以测试框架为例。 您不会为您启动的每个项目都编写测试框架。 您只需要使用JUnit或任何其他可用的JUnit,并可以选择在其之上进行构建。

总而言之,通常有针对大多数常见问题空间的现成解决方案。

Wiremock –现成的在线存根/模拟/虚拟服务

预打包解决方案的一种候选方案是无线存根/模拟/服务虚拟化解决方案。 Wiremock是用Java编写的开放源代码平台,这种解决方案已引起人们的关注,它可以在JUnit测试中使用,也可以作为独立过程来消除外部HTTP依赖关系。

在JUnit中使用Wiremock

让我们假设我们有一个天气预报应用程序,该应用程序与Forecast.io HTTP API进行对话,以显示伦敦的风速。 我们的应用程序以JSON字符串的形式获取伦敦的天气预报,然后解析响应,提取当前风速,并通过一个宁静的界面将其呈现给用户。

我们将从测试类中的JUnit规则开始。 这将是一个天气预报服务模拟,并假装为Forecast.io网络服务:

public class WeatherApplicationTest {
    @Rule
    public WireMockRule forecastIoService = new WireMockRule();
}

我们将添加天气应用对象,我们的测试系统。 开始和停止方法在设置和拆卸方法中调用。 我们从简单的快乐路径测试servesWindSpeedBasedOnForecastIoResponse

public class WeatherApplicationTest {
    @Rule
    public WireMockRule forecastIoService = new WireMockRule();

    private WeatherApplication weatherApplication = new WeatherApplication();

    @Before
    public void setUp() {
        weatherApplication.start();
    }

    @After
    public void tearDown() {
        weatherApplication.stop();
    }

    @Test
    public void servesWindSpeedBasedOnForecastIoResponse(){
        // TODO

快乐路径测试

我们将检查向我们的天气应用程序发送请求时,该请求是否转到了Forecast.io API,并且在返回响应时,该应用程序成功解析了该请求,将后缀添加到响应中,并提供了后缀给用户。

首先,我们从断言开始。 我们期望看到风速跟随每小时英里数的后缀:

@Test
public void servesWindSpeedBasedOnForecastIoResponse() {
    assertEquals("12.34mph", content.toString());
}

但是要实现这一点,我们需要与我们的应用程序对话,因此让我们使用Apache HTTP客户端来做到这一点:

@Test
public void servesWindSpeedBasedOnForecastIoResponse() throws IOException {

    Content content = Request.Get("http://localhost:" + weatherApplication.port() + "/wind-speed")
            .execute()
            .returnContent();

    assertEquals("12.34mph", content.toString());
}

现在,该应用程序将转至Forecast.io API并尝试获取预测。 因此,我们需要存根伪装成真正的API:

@Test
public void servesWindSpeedBasedOnForecastIoResponse() throws IOException {  
     forecastIoService.stubFor(get(urlEqualTo("/forecast/e67b0e3784104669340c3cb089412b67/51.507253,-0.127755"))
                .willReturn(aResponse().withBody("{\"currently\":{\"windSpeed\":12.34}}")));

    Content content = Request.Get("http://localhost:" + weatherApplication.port() + "/wind-speed")
             .execute()
             .returnContent();

        assertEquals("12.34mph", content.toString());
    }

我们告诉Wiremock(由ForecastIoService对象代表)创建一个存根,以获取对URL的获取请求
"/forecast/e67b0e3784104669340c3cb089412b67/51.507253,-0.127755"并返回具有给定json正文的响应。

真实的Forecast.io API返回的响应JSON有效负载约为2kb,因此为简化此测试,我仅包含了重要的位。 本文是关于展示如何使用Wiremock的。 它没有关注如何正确进行测试( TDD测试金字塔 )。

悲伤的道路测试

因此,现在您知道样例幸福道路的样子。 让我们也看看一条悲伤的道路。 假设每当Forecast.io服务出现问题时,我们都不希望出现异常。 每当Forecast.io方面存在问题时,我们都会向用户呈现503错误而不会爆炸,而是正常地失败。

再次,我们将与同一个/windspeed端点进行对话并存根forecast.io 。 我们告诉它为get请求创建存根,并且该存根应返回带有状态代码内部服务器错误(HTTP代码500)的响应。 我们断言,用户将收到一条错误消息和一个服务不可用(HTTP代码503)代码,而不是显示通用的堆栈跟踪:

@Test
    public void reportsErrorWhenForecastIoReturnsANonSuccessfulResponse()  throws IOException {
        forecastIoService.stubFor(get(urlEqualTo("/forecast/e67b0e3784104669340c3cb089412b67/51.507253,-0.127755"))
                .willReturn(aResponse().withStatus(SC_INTERNAL_SERVER_ERROR)));

        HttpResponse httpResponse = Request.Get("http://localhost:" + weatherApplication.port() + "/wind-speed")
                .execute()
                .returnResponse();

        assertEquals(503, httpResponse.getStatusLine().getStatusCode());
        assertEquals("ERROR", IOUtils.toString(httpResponse.getEntity().getContent()));
    }

这是一个非常简单的示例,但它演示了如何使用Wiremock自动执行快乐和悲伤的路径。

最后,这就是整个测试类的样子:

import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.fluent.Content;
import org.apache.http.client.fluent.Request;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static junit.framework.TestCase.assertEquals;

public class WeatherApplicationTest {
    @Rule
    public WireMockRule forecastIoService = new WireMockRule();

    private WeatherApplication weatherApplication = new WeatherApplication();
    @Before
    public void setUp() {
        weatherApplication.start();
    }

    @After
    public void tearDown() {
        weatherApplication.stop();
    }

    @Test
    public void servesWindSpeedBasedOnForecastIoResponse() throws IOException {
        forecastIoService.stubFor(get(urlEqualTo("/forecast/e67b0e3784104669340c3cb089412b67/51.507253,-0.127755"))
                .willReturn(aResponse().withBody("{\"currently\":{\"windSpeed\":12.34}}")));

        Content content = Request.Get("http://localhost:" + weatherApplication.port() + "/wind-speed")
                .execute()
                .returnContent();

        assertEquals("12.34mph", content.toString());
    }

    @Test
    public void reportsErrorWhenForecastIoReturnsANonSuccessfulResponse() throws IOException {
        forecastIoService.stubFor(get(urlEqualTo("/forecast/e67b0e3784104669340c3cb089412b67/51.507253,-0.127755"))
                .willReturn(aResponse().withStatus(SC_INTERNAL_SERVER_ERROR)));

        HttpResponse httpResponse = Request.Get("http://localhost:" + weatherApplication.port() + "/wind-speed")
                .execute()
                .returnResponse();

        assertEquals(503, httpResponse.getStatusLine().getStatusCode());
        assertEquals("ERROR", IOUtils.toString(httpResponse.getEntity().getContent()));
    }
}

这个简单的例子只是该工具可以做什么的一个示例。 完整的资源可以在我的github页面上找到。 有关更多详细信息,请参见Wiremock文档

手动探索性测试

我们在介绍中提到,在线存根有两个常见的用例。 正如我们刚刚看到的,第一个方法是充当自动化测试的双重测试。 接下来是图形控制台/ Web用户界面,用于进行手动探索性测试。

控制台中的Wiremock

可以从命令行调用Wiremock并通过HTTP接口使用例如Postman或cURL进行设置。 您可以通过向以下站点发送HTTP发布请求来设置新的存根:
http://<wiremock-host>:<wiremock-port>/__admin/mappings/new

与身体:

{
    "request": {
        "method": "GET",
        "url": "/some/thing"
    },
    "response": {
        "status": 200,
        "body": "Hello world!",
        "headers": {
            "Content-Type": "text/plain"
        }
    }
}

这等效于执行以下Java代码:

stubFor(get(urlEqualTo("/some/thing"))
            .willReturn(aResponse()
                .withHeader("Content-Type", "text/plain")
                .withBody("Hello world!")));

手动测试问题

如果您的测试人员不懂技术,或者不想花时间处理技术问题,您仍然可以帮助他们专注于他们最擅长的探索性测试。

首先,您可以在内部的Wiremock上开发Web界面或Swing GUI。 以我的经验,在长达12个月的时间内,可能需要1到10个开发人员天才能完善解决方案。

另外,您可以使用现成的产品,例如用于敏捷团队的Traffic Parrot 。 它是带有Web界面的在线双重测试,供敏捷团队中的开发人员和测试人员使用。 开发人员可以在他们的验收测试中使用Wiremock,并根据需要将存根定义导出到Traffic Parrot。 然后,测试人员可以使用Traffic Parrot Web UI创建双倍测试,以用于探索性测试。 我本人不得不在多家公司进行几次练习,因此我将通用解决方案整合到了“敏捷团队”的“交通鹦鹉”中,并已向公众发布。 它可以使您免于经历在开发它之前遇到的相同错误的挫败感。

存根方案

我在咨询任期内经历的另一个综合症是,对于给定的被测系统用例,经常需要多个端点或多个响应。 例如,如果要根据用户的位置向其显示当前风速,则可能必须与两个Web服务进行通信,一个Web服务获取GPS坐标,第二个Web服务获取天气预报。 JUnit测试设置部分的测试可能如下所示:

gpsService.stubFor(get(urlEqualTo("/what-are-my-coordinates"))
   .willReturn(aResponse().withBody("12.34,-0.12")));        
weatherService.stubFor(get(urlEqualTo("/forecast/12.34,-0.12"))
                
   .willReturn(aResponse().withBody("{\"currently\":{\"windSpeed\":3.55}}")));

在这种情况下,测试人员要寻找的是Web界面中的下拉菜单,其中包含针对坐标请求和天气预报坐标请求的预填充请求/响应对。 这样,他们就不必查找它们。

该功能在Traffic Parrot中也可用,因此您可以使用它来开始运行。

其他工具

如果您想在使用特定工具之前探索各种选择,则有很多选择。 我发现有40多种 Wiremock替代品,它们以不同的编程语言和不同的平台进行编码,从而提供了不同的功能集。

仅列举一些替代方案:

  • Mountebank (具有Java,Python,C#,Clojure等的绑定)
  • VCR (Ruby和Ruby on Rails最受欢迎的选择)
  • Stubby4j (使用不同的API设计方法的替代Java实现)

Wiremock仍然是当今Java最受欢迎的选择, Github上有1400多颗星和40个贡献者

更多信息

Christopher Batey的演讲是本文的一个很好的补充: 构建容错微服务的六项原则 ,他在其中描述了几种使用Wiremock测试不良路径的方案,包括测试断开的连接,慢速连接等。

下一步

关于作者

WB Software Consultancy的高级软件开发人员。 Wojciech在敏捷,自动化,XP,TDD,BDD,结对编程和纯净编码方面的写作中拥有数十年的动手编码经验。 WB Software Consultancy已为众多初创企业提供咨询服务,例如英国天空广播和劳埃德银行。 他们的最新产品是Traffic Parrot ,这是一种支持存根,模拟和服务虚拟化的软件工具。

翻译自: https://www.infoq.com/articles/Wiremock-testing-mocking-over-wire-stubs/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

ap框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值