【问题标题】:Stencil e2e Testing: mock a function in puppeteer browser contextStencil e2e 测试:在 puppeteer 浏览器上下文中模拟一个函数
【发布时间】:2020-07-18 19:46:19
【问题描述】:

我有 Stencil 组件,它使用 axios.get 从服务器获取一些数据(例如开发期间的 localhost:3000)。现在我有一个 e2e.ts 测试,它与其他几个组件一起测试这个组件。我想模拟 axios.get 函数以将我的测试与服务器隔离。在 spec.ts 测试中,我会使用 jest 和以下代码来模拟 axios:

import axios from 'axios';
import {myComponent} from './my-component';

const mock = jest.spyOn(axios, 'get');

test('get data', async () => {
  ...
  mock.mockResolvedValue('hello');
  ...
});

但这在 e2e 测试中不起作用。我已经尝试安装 jest-puppeteer,但我找不到任何示例说明如何使用 jest-puppeteer 使用 jest mocking API 来模拟函数。

任何示例代码将不胜感激。

附:注意:如果我使用 Puppeteer 拦截请求并响应它,我会收到“请求已处理”错误。下面是示例代码:

const page = await newE2EPage();
await page.setRequestInterception(true);
page.on('request', req => {
  if(req.url() === 'http://localhost:3000/') {
    request.respond({
      contentType: 'text/plain',
      headers: {'Access-Control-Allow-Origin': '*'},
      body: 'hello'
    })
  }
  else {
    request.continue({});
  }
});
await page.setContent('<my-component></my-component>');

【问题讨论】:

    标签: mocking jestjs puppeteer e2e-testing stenciljs


    【解决方案1】:

    我不能 100% 确定这个答案转换为 axios 的效果如何,但 fetch 可以做到这一点,我鼓励你使用它,因为它现在被浏览器广泛支持,并且 Stencil 会自动填充它如果需要。

    对于我们应用的 e2e 测试,我编写了以下脚本,您可以在初始化后将其添加到您的 e2e 页面:

    await page.addScriptTag({
      content: `
        window.originalFetch = window.fetch;
    
        window.requestsToIntercept = [];
    
        window.fetch = (...args) => (async(args) => {
          const result = await this.originalFetch(...args);
    
          for (const request of requestsToIntercept) {
            if (args[0].includes(request.url)) {
              result.json = async () => JSON.parse(request.response);
              result.text = async () => request.response;
            }
          }
    
          return result;
        })(args);`,
    });
    

    它会覆盖 fetch 实现并使用全局 requestsToIntercept 数组来存根响应。您可以在代码中添加一个辅助函数,例如

    const interceptRequests = async (requests: { url: string; response: string }[]) =>
      page.addScriptTag({
        content: `window.requestsToIntercept.push(...${JSON.stringify(requests)});`
      });
    

    然后像这样使用它

    interceptRequests([{ url: '/foo', response: { foo: 'bar' } }])
    

    这将拦截所有包含/foo 的请求,并使用给定的响应进行响应。


    我会让你按照你想要的方式将它重构为助手。我个人决定创建一个函数,为我创建一个newE2EPage 并将interceptRequests 作为方法添加到页面对象。


    顺便说一句,您无法在 Puppeteer 中启用请求拦截的原因是 Stencil 已经在内部使用它,因此在您的“on request”侦听器启动之前已经处理了请求(如错误消息所述)。在 Github 上有更改此设置的请求:https://github.com/ionic-team/stencil/issues/2326

    【讨论】:

    • 不错的答案。我选择了 axios,因为我想要一个统一的方法来处理我的服务器端 Node.js 和我的客户端代码。
    • 我明白了。您可以尝试isomorphic-unfetchnode-fetch,这样您就可以在Node.js 中使用相同的fetch API。
    猜你喜欢
    • 2019-09-09
    • 2021-04-26
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    相关资源
    最近更新 更多