Cypress 10 E2E测试中方法Stub失效问题求助
Cypress E2E测试Stub类实例方法无效的原因及解决办法
核心原因
E2E测试和组件测试的运行环境完全不同:
- 组件测试是在Node环境中直接渲染组件,测试代码和组件代码共享同一个运行上下文,你导入的
userUtil实例和组件使用的是同一个,所以Stub能生效。 - E2E测试中,测试代码运行在Node端,而应用代码运行在浏览器端,两者是完全隔离的两个环境。你在测试代码里导入并Stub的
userUtil,和浏览器里应用实际调用的userUtil是两个完全独立的实例,自然不会影响到应用的执行逻辑。
解决办法
方法1:将实例挂载到浏览器全局对象,在浏览器环境中Stub
首先在应用代码的userUtil.ts中,仅在测试环境下把实例挂载到window:
export class UserUtil { public async init() { // ...原逻辑 } } const userUtil = new UserUtil(); export default userUtil; // 仅测试环境暴露到全局 if (process.env.NODE_ENV === 'test') { (window as any).userUtil = userUtil; }
然后在测试代码中,先访问页面(确保应用代码加载完成),再通过cy.window()获取浏览器环境中的实例并Stub:
beforeEach(() => { cy.visit('/'); cy.window().then((win) => { // 对浏览器环境中的userUtil实例进行Stub cy.stub(win.userUtil, 'init').as('init'); }); });
方法2:提供依赖注入入口,替换实例
如果不想直接暴露全局变量,可以在应用代码中添加一个实例替换方法:
export class UserUtil { public async init() { // ...原逻辑 } } let userUtilInstance = new UserUtil(); // 提供替换实例的方法 export const setUserUtilInstance = (instance: UserUtil) => { userUtilInstance = instance; }; export default userUtilInstance;
测试代码中,通过浏览器环境调用替换方法,传入Stub后的实例:
beforeEach(() => { cy.visit('/'); cy.window().then((win) => { // 创建一个新的UserUtil实例并Stub其init方法 const stubbedInstance = new win.UserUtil(); cy.stub(stubbedInstance, 'init').as('init'); // 替换应用中的实例 win.setUserUtilInstance(stubbedInstance); }); });
注意事项
- E2E测试中所有对应用代码的修改,都必须通过
cy.window()进入浏览器环境操作,不能直接在测试代码中修改应用的变量或实例。 - 全局变量的暴露要限制在测试环境,避免生产环境泄露不必要的代码。
内容的提问来源于stack exchange,提问作者Rachel Fishbein
相关产品推荐
相关产品推荐

