模拟对象
模拟对象是表示网络模拟的对象,包含有关与给定url和filterOptions匹配的请求的信息。可以使用mock命令获取该对象。
信息
请注意,使用mock命令需要支持Chrome DevTools协议。
如果你在基于Chromium的浏览器中本地运行测试,或者
使用Selenium Grid v4或更高版本,则可以获得这种支持。在云端运行
自动化测试时不能使用此命令。在自动化协议部分了解更多信息。
你可以在我们的模拟和监视指南中阅读更多关于在WebdriverIO中模拟请求和响应的信息。
属性
模 拟对象包含以下属性:
| 名称 | 类型 | 详情 |
|---|---|---|
url | String | 传递给mock命令的url |
filterOptions | Object | 传递给mock命令的资源过滤选项 |
browser | Object | 用于获取mock对象的浏览器对象。 |
calls | Object[] | 有关匹配的浏览器请求的信息,包含诸如url、method、headers、initialPriority、referrerPolic、statusCode、responseHeaders和body等属性 |
方法
模拟对象提供了各种命令,列在mock部分中,允许用户修改请求或响应的行为。
事件
模拟对象是一个EventEmitter,为你的用例 发出了几个事件。
以下是事件列表。
request
当启动与模拟模式匹配的网络请求时,会发出此事件。请求在事件回调中传递。
请求接口:
interface RequestEvent {
requestId: number
request: Matches
responseStatusCode: number
responseHeaders: Record<string, string>
}
overwrite
当使用respond或respondOnce覆盖网络响应时,会发出此事件。响应在事件回调中传递。
响应接口:
interface OverwriteEvent {
requestId: number
responseCode: number
responseHeaders: Record<string, string>
body?: string | Record<string, any>
}
fail
当使用abort或abortOnce中止网络请求时,会发出此事件。失败在事件回调中传递。
失败接口:
interface FailEvent {
requestId: number
errorReason: Protocol.Network.ErrorReason
}
match
当添加新匹配时,在continue或overwrite之前发出此事件。匹配在事件回调中传递。
匹配接口:
interface MatchEvent {
url: string // 请求URL(不包含片段)。
urlFragment?: string // 请求URL的片段,以哈希开头(如果存在)。
method: string // HTTP请求方法。
headers: Record<string, string> // HTTP请求头。
postData?: string // HTTP POST请求数据。
hasPostData?: boolean // 当请求有POST数据时为true。
mixedContentType?: MixedContentType // 请求的混合内容导出类型。
initialPriority: ResourcePriority // 发送请 求时资源请求的优先级。
referrerPolicy: ReferrerPolicy // 请求的引用策略,如https://www.w3.org/TR/referrer-policy/中定义的。
isLinkPreload?: boolean // 是否通过链接预加载加载。
body: string | Buffer | JsonCompatible // 实际资源的响应体。
responseHeaders: Record<string, string> // HTTP响应头。
statusCode: number // HTTP响应状态码。
mockedResponse?: string | Buffer // 如果模拟发出事件,同时修改了其响应。
}
continue
当网络响应既未被覆盖也未被中断,或者响应已被另一个模拟发送时,会发出此事件。requestId在事件回调中传递。
示例
获取待处理请求的数量:
let pendingRequests = 0
const mock = await browser.mock('**') // 匹配所有请求很重要,否则,得到的值可能非常令人困惑。
mock.on('request', ({request}) => {
pendingRequests++
console.log(`matched request to ${request.url}, pending ${pendingRequests} requests`)
})
mock.on('match', ({url}) => {
pendingRequests--
console.log(`resolved request to ${url}, pending ${pendingRequests} requests`)
})
在404网络失败时抛出错误:
browser.addCommand('loadPageWithout404', (url, {selector, predicate}) => new Promise(async (resolve, reject) => {
const mock = await this.mock('**')
mock.on('match', ({url, statusCode}) => {
if (statusCode === 404) {
reject(new Error(`request to ${url} failed with "Not Found"`))
}
})
await this.url(url).catch(reject)
// 在这里等待,因为一些请求可能仍在挂起
if (selector) {
await this.$(selector).waitForExist().catch(reject)
}
if (predicate) {
await this.waitUntil(predicate).catch(reject)
}
resolve()
}))
await browser.loadPageWithout404(browser, 'some/url', { selector: 'main' })
确定是否使用了模拟响应值:
const firstMock = await browser.mock('**/foo/**')
const secondMock = await browser.mock('**/foo/bar/**')
firstMock.respondOnce({id: 3, title: 'three'})
secondMock.respond({id: 4, title: 'four'})
firstMock.on('overwrite', () => {
// 对'**/foo/**'的第一个请求触发
}).on('continue', () => {
// 对'**/foo/**'的其余请求触发
})
secondMock.on('continue', () => {
// 对'**/foo/bar/**'的第一个请求触发
}).on('overwrite', () => {
// 对'**/foo/bar/**'的其余请求触发
})
在此示例中,firstMock首先定义并有一个respondOnce调用,所以secondMock的响应值不会用于第一个请求,但会用于其余请求。