对同一个端点的多个响应的伪造者请求拦截最佳实践 [英] Puppeteer request interception best practice for multiple responses to the same endpoint

查看:59
本文介绍了对同一个端点的多个响应的伪造者请求拦截最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于单元测试,我拦截所有请求,然后以特定日期的模拟日期作为响应.我有一个 pageMockedRequests 函数,它将在端点上打开.

For my unit tests I intercept all requests and then responding with mocked date for specific endpoints. I have a pageMockedRequests function that will switch on the endpoint.

当我想根据被调用的次数更改要发送回的响应时,就会遇到问题.

My issue comes when I want to change the response I am sending back depending on how many times it has been called.

    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 上对其进行更改.

The above shows that ENDPOINT.B for the second time will be different from the first response. I'm currently changing it on count.

还有其他人这样做吗?

推荐答案

在只有两种可能的情况下,使用 if switch 枚举每种情况都很好.但是,当您选择了3个或4个以上的选项时,环复杂性超出了可维护性.

Enumerating every case with an if or switch is fine when there's only a couple of possibilities. But when you wind up with more than 3 or 4 options, the cyclomatic complexity increases beyond maintainability.

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

A scalable approach uses a data structure that is basically a lookup table for all of your request parameters. One approach is to use a nested object keyed by URL. Each URL points to an inner object keyed by method which keys to an array of responses. For each response array, you could keep an index counter that steps forward whenever responses are sent, or mutate the array by popping or shifting.

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

Here's a sketch of this approach:

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"})在反序列化期间使用前每个响应的功能.

The data structure of responses by endpoint and method is regular and can be serialized as an external file, although you may need to add body: async () => ({"your": "body"}) functions per response before use during deserialization.

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

This approach also nicely handles bad requests without changing any code or adding to your switch or if-else chain.

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

If you need to reset your mocks occasionally, use your test runner's beforeEach block or write a function that returns it fresh.

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

Even if you're not using this exact mocking approach, this pattern is generic and should save you from if/switch sadness.

这篇关于对同一个端点的多个响应的伪造者请求拦截最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆