如何在赛普拉斯上使用PactJS?

时间:2020-03-02 19:36:55

标签: cypress pact

我想成为PactJSCypress的朋友。

这就是问题,因为cypress集成测试在浏览器中运行,所以节点环境不可用,因此我无法在测试中的任何地方使用Pact对象。

通过Cypress任务

尽管如此,我可以实现cypress task,并将所有与cypress相关的代码移至该任务,并通过其他任务进行所有通信。这样,流程就变得太复杂了,它需要在任务中支持Pact对象的生命周期,并复制所有消息。像这样:

cypress / plugins / index.js

const {Pact} = require("@pact-foundation/pact")
  module.exports = (on) => {
  on("task", {
    createPactServer() {
      return new Pact({
        consumer: "TodoApp",
        provider: "TodoService",
        port: 8501,
        // log: path.resolve(process.cwd(), "logs", "pact.log"),
        // dir: path.resolve(process.cwd(), "pacts"),
        logLevel: "info",
      })
    }
  })
}

cypress / integration / test.js

describe("Login page", (): void => {
  it("should log in", (): void => {
    let a = cy.task('createPactServer', );
    // do rest
    // manage verify
    // handle errors from verify
    //  shutdown pact server
    // handle all other lifecycle events.
  });
});

我想避免这种情况!

通过柏树路线

{木也随附route,可以模拟网络并存根响应。我想知道是否有任何方法可以将它们混合使用,所以我什至根本不会监听带有Pact服务器的端口。我没有发现任何以为我没有调查太久的方法。在我看来,还有一个pact-web只是没有http服务器的模拟部分,但是没有关于将其与API集成的文档。我还发现该协定使用了ruby文件,这可能使它无法在非节点环境中不使用http服务器。

我想知道是否无论如何尝试将它们耦合在一起,什么是首选方式。

2 个答案:

答案 0 :(得分:1)

我刚刚创建了一个demonstration应用程序,将两者结合在一起。我发现经验是quite good。它的作用:

  1. Pact插件将为每个注册的交互动态创建一个server和相应的route(这样很快)
  2. 它将设置默认路由处理程序以捕获未明确配置的任何请求(以避免丢失实际请求,从而失去信心)
  3. 仍然可以使用路由别名和cy.wait,因此保留了开发经验,就像您没有使用Pact一样。

我打算将其提取到单独的cypress插件中。

下面是使用该插件的示例测试代码的样子:

示例

import { Matchers } from "@pact-foundation/pact-web";
const { like, eachLike } = Matchers;

let server;

const expectedProduct = {
  id: "10",
  type: "CREDIT_CARD",
  name: "28 Degrees",
};

describe("Product page", () => {
  describe("when products exist", () => {
    before(() => {
      cy.mockServer({
        consumer: "example-cypress-consumer",
        provider: "example-provider",
      }).then(opts => {
        server = opts
      })
    });

    it("can navigate to an individual product", () => {
      cy.addMockRoute({
        server,
        as: 'products',
        state: "products exist",
        uponReceiving: "a request to all products",
        withRequest: {
          method: "GET",
          path: "/products",
        },
        willRespondWith: {
          status: 200,
          headers: {
            "Content-Type": "application/json; charset=utf-8",
          },
          body: eachLike(expectedProduct),
        },
      });
      cy.addMockRoute({
        server,
        as: 'product',
        state: "a product with ID 10 exists",
        uponReceiving: "a request to get a product",
        withRequest: {
          method: "GET",
          path: "/product/10",
        },
        willRespondWith: {
          status: 200,
          headers: {
            "Content-Type": "application/json; charset=utf-8",
          },
          body: like(expectedProduct),
        },
      });

      // Navigate to products listing page
      cy.visit("http://localhost:3000");
      cy.wait("@products");

      // Filter to the product we want
      cy.get("#input-product-search").type("28 degrees");

      // Navigate to individual product
      cy.contains("See more!").click();
      cy.wait("@product");

      // ... Assert something about product page
    });
  });
});

最终思想

我仍然认为,在可能的情况下,在正确的层进行这种形式的测试是有意义的,在此您可以更直接地针对API客户端。但是这种方法可以解决许多问题(更广泛的受众,非常好的开发经验和翻新用例),并且如果使用得当,对于许多人来说都是一条不错的途径。

这是一段视频https://youtu.be/jTuuYMFJBBQ,其中显示:

  1. 首次运行会​​导航到/,后者会调用产品列表API /products
  2. 第二次运行将测试扩展到点击进入需要点击/products/:id的产品页面。测试失败,因为尚未在Cypress或Pact中配置交互功能
  3. 在{ila}中添加product/:id互动!

答案 1 :(得分:-3)

为什么要把柏树和契约配对?我以前都曾经使用过,我认为最好避免这种依赖。

一方面,您可以将赛普拉斯用于E2E测试,因为赛普拉斯适用于在浏览器中运行的任何程序。这意味着您不需要直接引用服务,控制器等。 另一方面,您可以使用Pact JS(带有mocha)进行合同测试。如您所知,Pact遵循消费者驱动的合同方法。这意味着您必须从使用者创建pact文件,因为您必须针对控制器(或http call方法)进行单元测试,而不能使用cypress。

相关问题