使用Puppeteer与Mocha时部分方法无法跳转至定义的问题
问题分析与解决
代码示例
const puppeteer = require('puppeteer'); describe('test', async () => { let browser, page; before(async () => { browser = await puppeteer.launch(); page = browser.newPage(); }) after(async () => { await browser.close(); }) it('test1', async () => { await page.goto('https://www.google.com'); await page.goto('https://www.yahoo.com'); }) })
为什么before()里初始化后无法跳转方法定义?
这是编辑器(比如VS Code)的类型推断限制:
browser和page用let声明时是空变量,只有在before()钩子内部完成赋值,编辑器才能识别它们是Puppeteer的Browser和Page实例。- 但
before()是Mocha的异步钩子,编辑器没法跨钩子推断变量类型——在after()和it()里,编辑器只能把browser和page识别为any类型,没法关联到Puppeteer的具体类,自然找不到.close()、.goto()的方法定义,也就没法Ctrl+click跳转。
移出before()后能跳转但脚本跑不了的原因?
你把初始化代码移出before()后,应该是直接写在了describe()的回调里,问题出在Mocha的执行机制:
- Mocha的
describe()回调是同步执行的,它不会等待内部的异步操作完成。也就是说,await puppeteer.launch()还没执行完,Mocha就已经开始运行before()、after()和it()里的代码了。 - 此时
browser和page要么是未完成的Promise,要么还没赋值,后续调用.close()、.goto()时会抛出Cannot read property 'xxx' of undefined之类的错误,导致脚本运行失败。 - 另外,
describe()的回调本身不支持async——Mocha会忽略这个回调返回的Promise,异步初始化的代码根本不会被正确等待。
兼顾跳转和运行的解决方法
给变量加上显式类型标注,让编辑器能识别变量类型,同时保持初始化逻辑在before()里:
纯JS用JSDoc标注
const puppeteer = require('puppeteer'); /** @type import('puppeteer').Browser */ let browser; /** @type import('puppeteer').Page */ let page; describe('test', () => { before(async () => { browser = await puppeteer.launch(); page = await browser.newPage(); // 注意:原代码漏了await,newPage()是异步方法必须加 }) after(async () => { await browser.close(); }) it('test1', async () => { await page.goto('https://www.google.com'); await page.goto('https://www.yahoo.com'); }) })
TypeScript直接加类型
import puppeteer, { Browser, Page } from 'puppeteer'; let browser: Browser; let page: Page; describe('test', () => { before(async () => { browser = await puppeteer.launch(); page = await browser.newPage(); }) after(async () => { await browser.close(); }) it('test1', async () => { await page.goto('https://www.google.com'); await page.goto('https://www.yahoo.com'); }) })
这样编辑器能正确识别变量类型,Ctrl+click可以跳转方法定义,同时代码能正常运行——因为初始化逻辑仍在before()里,Mocha会正确等待钩子完成后再执行测试用例。
内容的提问来源于stack exchange,提问作者user25256425
相关产品推荐
相关产品推荐

