Puppeteer请求拦截管理的最佳实践

时间:2018-06-15 10:05:02

标签: javascript jestjs coded-ui-tests puppeteer

对于我的uitests,我正在拦截所有请求,然后以特定端点的模拟日期进行响应。我有一个pageMockedRequests函数,可以打开enpoint。

我的问题出现了,当我想根据发送的次数改变响应时,取决于它被调用的次数。

    const pageMockedRequests = (request) => {
      switch (request.url()) {
        case ENDPOINTS.A:
          return request.respond(jsonResponseWrapper(returnValidToken(), 200));
        case ENDPOINTS.B:
          if (count === 0) {
            return request.respond(jsonResponseWrapper({RESPONSE FOR 1st CALL}, 200));
          } else if (count === 1) {
            return request.respond(jsonResponseWrapper({RESPONSE FOR 2nd CALL}, 200));
          }
        default:
          return request.abort();
      }
    };

...因此,上面显示ENDPOINT.B第二次与第一次响应不同。我目前正在count更改它。

其他人有不同的做法吗?

3 个答案:

答案 0 :(得分:0)

对此实现使用计数似乎可以。有多少种不同的可能性?如果只有两个选项,请简化:

jsx

答案 1 :(得分:0)

您可以为Puppeteer使用Mockiavelli请求模拟库。它的一次性模拟功能(https://github.com/hltech/mockiavelli#one-time-mocks)可以为第一次和第二次呼叫定义不同的响应。

答案 2 :(得分:0)

在只有两种可能性的情况下,使用ifswitch枚举每种情况都很好。但是,当您选择3个或4个以上的选项时,cyclomatic complexity会超出可维护性范围。

可伸缩的方法使用的数据结构基本上是所有请求参数的查找表。一种方法是使用以URL为键的嵌套对象。每个URL指向一个由方法锁定的内部对象,该方法锁定响应数组。对于每个响应数组,您可以保留一个索引计数器,无论何时发送响应,索引计数器都会前进,或者通过弹出或移位来使数组变异。

以下是这种方法的示意图:

const responsesByEndpoint = {
  "https://www.example.com/api/users": {
    GET: [/* mocked responses */],
    POST: [/* mocked responses */],
    PUT: [/* mocked responses */],
    DELETE: [/* mocked responses */],
  },
  "https://www.example.com/api/posts": {
    GET: [/* mocked responses */],
    POST: [/* mocked responses */],
  },
  "https://www.example.com/api/login": {
    POST: [/* mocked responses */],
  },
  // ...
};

page.on("request", request => {
  try {
    const response = responsesByEndpoint
      [request.url()][request.method()].shift()
    ;
    
    if (response === undefined) {
      throw Error;
    }

    request.respond(response);
  }
  catch (err) {
    request.abort(); // or: request.continue();
  }
});

通过端点和方法进行响应的数据结构是常规的,可以序列化为外部文件,尽管在反序列化过程中可能需要在每个响应之前添加body: async () => ({"your": "body"})个函数。

这种方法还可以很好地处理错误请求,而无需更改任何代码或不添加到您的switchif-else链中。

如果您偶尔需要重置模拟,请使用测试运行器的beforeEach块或编写一个将其重新生成的函数。

即使您没有使用这种精确的模拟方法,这种模式也是通用的,应该使您免于if / switch的悲伤。