请求模拟和监听
WebdriverIO 内置了修改网络响应的支持,让您可以专注于测试前端应用程序,而无需设置后端或模拟服务器。您可以在测试中为REST API请求等网络资源定义自定义响应,并动态修改它们。
信息
请注意,使用mock
命令需要支持Chrome DevTools协议。如果您在基于Chromium的浏览器中本地运行测试,通过Selenium Grid v4或更高版本,或通过支持Chrome DevTools协议的云厂商(如SauceLabs、BrowserStack、LambdaTest)运行测试,则可以获得该支持。一旦所需的原语在Webdriver Bidi中落地并在相应的浏览器中实现,将提供完整的跨浏览器支持。
创建模拟
在修改任何响应之前,您首先需要定义一个模拟。这个模拟通过资源URL来描述,可以通过请求方法或头信息进行过滤。资源支持通过minimatch的全局表达式:
// mock all resources ending with "/users/list"
const userListMock = await browser.mock('**/users/list')
// or you can specify the mock by filtering resources by headers or
// status code, only mock successful requests to json resources
const strictMock = await browser.mock('**', {
// mock all json responses
requestHeaders: { 'Content-Type': 'application/json' },
// that were successful
statusCode: 200
})
指定自定义响应
一旦定义了模拟,您就可以为其定义自定义响应。这些自定义响应可以是一个对象(用于响应JSON),一个本地文件(用于响应自定义固定数据)或一个Web资源(用互联网上的资源替换响应)。
模拟API请求
为了模拟您期望JSON响应的API请求,您只需要在模拟对象上调用respond
,并传入您想要返回的任意对象,例如:
const mock = await browser.mock('https://todo-backend-express-knex.herokuapp.com/')
mock.respond([{
title: 'Injected (non) completed Todo',
order: null,
completed: false
}, {
title: 'Injected completed Todo',
order: null,
completed: true
}], {
headers: {
'Access-Control-Allow-Origin': '*'
},
fetchResponse: false
})
await browser.url('https://todobackend.com/client/index.html?https://todo-backend-express-knex.herokuapp.com/')
await $('#todo-list li').waitForExist()
console.log(await $$('#todo-list li').map(el => el.getText()))
// outputs: "[ 'Injected (non) completed Todo', 'Injected completed Todo' ]"
您还可以通过传入一些模拟响应参数来修改响应头和状态码,如下所示:
mock.respond({ ... }, {
// respond with status code 404
statusCode: 404,
// merge response headers with following headers
headers: { 'x-custom-header': 'foobar' }
})
如果您希望模拟完全不调用后端,可以将fetchResponse
标志设置为false
。
mock.respond({ ... }, {
// do not call the actual backend
fetchResponse: false
})
建议将自定义响应存储在固定文件中,这样您可以在测试中直接引入它们,如下所示:
// requires Node.js v16.14.0 or higher to support JSON import assertions
import responseFixture from './__fixtures__/apiResponse.json' assert { type: 'json' }
mock.respond(responseFixture)