跳到主要内容

模拟对象

模拟对象是表示网络模拟的对象,包含有关与给定urlfilterOptions匹配的请求的信息。可以使用mock命令获取该对象。

信息

请注意,使用mock命令需要支持Chrome DevTools协议。 如果你在基于Chromium的浏览器中本地运行测试,或者 使用Selenium Grid v4或更高版本,则可以获得这种支持。在云端运行 自动化测试时不能使用此命令。在自动化协议部分了解更多信息。

你可以在我们的模拟和监视指南中阅读更多关于在WebdriverIO中模拟请求和响应的信息。

属性

模拟对象包含以下属性:

名称类型详情
urlString传递给mock命令的url
filterOptionsObject传递给mock命令的资源过滤选项
browserObject用于获取mock对象的浏览器对象
callsObject[]有关匹配的浏览器请求的信息,包含诸如urlmethodheadersinitialPriorityreferrerPolicstatusCoderesponseHeadersbody等属性

方法

模拟对象提供了各种命令,列在mock部分中,允许用户修改请求或响应的行为。

事件

模拟对象是一个EventEmitter,为你的用例发出了几个事件。

以下是事件列表。

request

当启动与模拟模式匹配的网络请求时,会发出此事件。请求在事件回调中传递。

请求接口:

interface RequestEvent {
requestId: number
request: Matches
responseStatusCode: number
responseHeaders: Record<string, string>
}

overwrite

当使用respondrespondOnce覆盖网络响应时,会发出此事件。响应在事件回调中传递。

响应接口:

interface OverwriteEvent {
requestId: number
responseCode: number
responseHeaders: Record<string, string>
body?: string | Record<string, any>
}

fail

当使用abortabortOnce中止网络请求时,会发出此事件。失败在事件回调中传递。

失败接口:

interface FailEvent {
requestId: number
errorReason: Protocol.Network.ErrorReason
}

match

当添加新匹配时,在continueoverwrite之前发出此事件。匹配在事件回调中传递。

匹配接口:

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的响应值不会用于第一个请求,但会用于其余请求。

Welcome! How can I help?

WebdriverIO AI Copilot