我有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模拟API模拟函数。
任何示例代码将不胜感激。
P.S。注意:如果我使用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>');
[我不确定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
作为方法添加到页面对象。
BTW之所以不能在Puppeteer中启用请求拦截,是因为Stencil已在内部使用它,因此,在“按请求”侦听器启动之前,该请求已经被处理(错误消息指出)。在Github上有一个更改要求:https://github.com/ionic-team/stencil/issues/2326。