You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebDriver.io使用wdio-intercept-service遇TypeError错误求助

问题描述

我尝试用WebDriver.io搭配wdio-intercept-service执行测试,运行npm run test时出现TypeError: WebdriverAjax is not a function错误。此前尝试用Nock拦截并修改请求响应也未成功,以下是相关代码及完整报错信息,希望解决这两个问题:


package.json

{
  "name": "my-new-project",
  "type": "module",
  "devDependencies": {
    "@wdio/cli": "^8.8.8",
    "@wdio/local-runner": "^8.8.8",
    "@wdio/mocha-framework": "^8.8.7",
    "@wdio/spec-reporter": "^8.8.7",
    "chromedriver": "^112.0.0",
    "geckodriver": "^3.2.0",
    "msedgedriver": "^91.0.0",
    "nock": "^13.3.1",
    "wdio-chromedriver-service": "^8.1.1",
    "wdio-edgedriver-service": "^2.1.2",
    "wdio-geckodriver-service": "^4.1.1",
    "wdio-intercept-service": "^4.4.0"
  },
  "scripts": {
    "wdio": "wdio run ./wdio.conf.js",
    "test": "wdio run ./wdio.conf.js --spec test/specs/test1.js"
  },
  "dependencies": {
    "webdriverio": "^8.8.8"
  }
}

test1.js

import { remote } from 'webdriverio';
import WebdriverAjax from 'wdio-intercept-service'

const WDIO_OPTIONS = {
    port: 9515,
    path: '/',
    capabilities: {
        browserName: 'chrome'
    },
}

let browser;
const interceptServiceLauncher = WebdriverAjax();

beforeAll(async () => {
    browser = await remote(WDIO_OPTIONS)
    interceptServiceLauncher.before(null, null, browser)
})

beforeEach(async () => {
    interceptServiceLauncher.beforeTest()
})

afterAll(async () => {
    await client.deleteSession()
});

async function time(pause = 1000) {
    const starttime = new Date().getTime();
    await browser.pause(pause);
    const endtime = new Date().getTime();
    console.log("-------------------------------->", pause, endtime - starttime); // outputs: 3000
}

describe('Test Case Name', () => {
    it('should intercept and modify a request with Nock', async () => {
        await time(1000);
        browser.url('https://jsonplaceholder.typicode.com');
        browser.setupInterceptor(); // capture ajax calls
        browser.expectRequest('GET', '/posts/1', 200); // expect GET request to /api/foo with 200 statusCode
        browser.expectRequest('POST', '/posts/1', 400); // expect POST request to /api/foo with 400 statusCode
        browser.expectRequest('GET', /\/posts\/1/, 200); // can validate a URL with regex, too
        browser.click('#button'); // button that initiates ajax request
        browser.pause(1000); // maybe wait a bit until request is finished
        browser.assertRequests(); // validate the requests
        await time(5000);
    });
});

报错信息

DevTools listening on ws://127.0.0.1:55425/devtools/browser/0d726522-6a04-4054-820c-b9805dde997a
[0-0] 2023-05-01T08:58:50.200Z ERROR @wdio/runner: Error: Unable to load spec files quite likely because they rely on `browser` object that is not fully initialised.
[0-0] `browser` object has only `capabilities` and some flags like `isMobile`.
[0-0] Helper files that use other `browser` commands have to be moved to `before` hook.
[0-0] Spec file(s): file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js
[0-0] Error: TypeError: WebdriverAjax is not a function
[0-0]     at file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js:13:34
[0-0]     at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
[0-0]     at async Promise.all (index 0)
[0-0]     at async ESMLoader.import (node:internal/modules/esm/loader:533:24)
[0-0]     at async importModuleDynamicallyWrapper (node:internal/vm/module:438:15)
[0-0]     at async formattedImport (C:\Users\lbott\node-project\webdriver.io\node_modules\mocha\lib\nodejs\esm-utils.js:9:14)
[0-0]     at async Object.exports.requireOrImport (C:\Users\lbott\node-project\webdriver.io\node_modules\mocha\lib\nodejs\esm-utils.js:42:28)
[0-0]     at async Object.exports.loadFilesAsync (C:\Users\lbott\node-project\webdriver.io\node_modules\mocha\lib\nodejs\esm-utils.js:100:20)
[0-0]     at async MochaAdapter._loadFiles (file:///C:/Users/lbott/node-project/webdriver.io/node_modules/@wdio/mocha-framework/build/index.js:67:13)
[0-0]     at async MochaAdapter.init (file:///C:/Users/lbott/node-project/webdriver.io/node_modules/@wdio/mocha-framework/build/index.js:62:9)
[0-0]  Error:  Unable to load spec files quite likely because they rely on `browser` object that is not fully initialised.
`browser` object has only `capabilities` and some flags like `isMobile`.
Helper files that use other `browser` commands have to be moved to `before` hook.
Spec file(s): file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js
Error: TypeError: WebdriverAjax is not a function
    at file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js:13:34
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
[0-0] FAILED in chrome - file:///C:/Users/lbott/node-project/webdriver.io/test/specs/test1.js

之前的Nock测试代码

describe('Test Case Name', () => {
    it('should intercept and modify a request with Nock', async () => {
        await time(1000);
        nock('https://jsonplaceholder.typicode.com')
            .get('/posts/1')
            .reply(200, { body: 'hello world' });
        await browser.url('https://jsonplaceholder.typicode.com/posts/1');
        await browser.waitUntil(() => {
            return browser.$('body').getText().includes('hello world');
        }, {
            timeout: 5000,
            timeoutMsg: 'expected body to contain "hello world" after 5s',
        });
        await time(5000);
    });
});

解决方案

1. 修复TypeError: WebdriverAjax is not a function错误

wdio-intercept-service不需要手动导入和初始化,正确做法是在WDIO配置文件中注册服务,由WDIO自动注入功能到全局browser对象:

步骤1:修改wdio.conf.js

将intercept服务添加到services数组:

export const config = {
    // 其他配置(端口、capabilities等)
    services: ['chromedriver', 'intercept'],
    framework: 'mocha',
    // 其他配置
}

步骤2:修改test1.js

删除手动初始化浏览器和WebdriverAjax的代码,使用WDIO自动提供的全局browser,同时修正afterAll中的错误变量:

let browser;

afterAll(async () => {
    await browser.deleteSession() // 将client改为browser
});

async function time(pause = 1000) {
    const starttime = new Date().getTime();
    await browser.pause(pause);
    const endtime = new Date().getTime();
    console.log("-------------------------------->", pause, endtime - starttime);
}

describe('Test Case Name', () => {
    it('should intercept requests', async () => {
        await time(1000);
        await browser.url('https://jsonplaceholder.typicode.com');
        await browser.setupInterceptor();
        await browser.expectRequest('GET', '/posts/1', 200);
        
        // 原页面无#button,改为直接触发请求的操作
        await browser.url('https://jsonplaceholder.typicode.com/posts/1');
        
        await browser.pause(1000);
        await browser.assertRequests();
        await time(5000);
    });
});

2. 修复Nock无法拦截浏览器请求的问题

Nock仅能拦截Node.js环境发出的HTTP请求,浏览器的请求独立于Node.js进程,因此无法被Nock捕获。要修改浏览器请求的响应,直接使用wdio-intercept-service的mock方法:

describe('Test Case Name', () => {
    it('should modify request response', async () => {
        await browser.url('https://jsonplaceholder.typicode.com');
        
        // 拦截目标请求并修改响应内容
        const mock = await browser.mock('https://jsonplaceholder.typicode.com/posts/1', { method: 'GET' });
        mock.respond({ body: 'hello world' }, { statusCode: 200 });
        
        await browser.url('https://jsonplaceholder.typicode.com/posts/1');
        await browser.waitUntil(async () => {
            const bodyText = await browser.$('body').getText();
            return bodyText.includes('hello world');
        }, {
            timeout: 5000,
            timeoutMsg: 'expected body to contain "hello world" after 5s',
        });
    });
});

内容的提问来源于stack exchange,提问作者Luca Bottoni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 04:28:08