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

如何在Cypress中Mock Vite项目的自定义TypeScript函数返回结果?

问题:如何在Cypress测试中Mock自定义TypeScript模块的方法?

我在本地环境创建了一个新的Vite TypeScript项目,项目入口代码如下:

import './style.css'
import { add } from './calculator'

document.querySelector<HTMLSpanElement>('#app')!.innerHTML = add(2, 3).toString()

同时新增了calculator.ts文件,包含add方法:

export function add(a: number, b: number): number {
  return a + b
}

已安装Cypress 10.11.0,编写测试用例如下:

import * as calculator from "../../src/calculator";

describe('empty spec', () => {
  it('passes', () => {
    cy.visit('http://localhost:5173/', {
      onBeforeLoad() {
        cy.stub(calculator, 'add').returns(10)
      }
    })
  })
})

测试结果:页面仍显示5,无法通过Stub让页面显示指定的10。尝试将stub放在onBeforeLoad之外,能Mockdocument.getElementById这类DOM函数,但无法对自定义脚本生效。


核心原因

你当前Stub的是测试文件中导入的calculator模块实例,而应用代码里导入的是另一个独立的模块实例,两者互不影响,所以Stub不会作用到应用代码上。

解决方案一:使用自定义命令拦截Vite模块请求

针对Vite的ES模块加载机制,我们可以通过拦截模块请求,替换为Mock版本:

  1. 在Cypress的support/e2e.ts中添加自定义命令:
Cypress.Commands.add('mockModule', (modulePath: string, mockExports: Record<string, any>) => {
  // 转义模块路径中的特殊字符,适配正则匹配
  const escapedPath = modulePath.replace(/\./g, '\\.')
  cy.intercept('GET', new RegExp(`${escapedPath}\\.ts`), (req) => {
    // 生成Mock模块的代码内容
    const mockCode = Object.entries(mockExports).map(([key, value]) => {
      if (typeof value === 'function') {
        return `export const ${key} = ${value.toString()};`
      }
      return `export const ${key} = ${JSON.stringify(value)};`
    }).join('\n')
    req.reply(mockCode)
  })
})
  1. 修改测试用例,在访问页面前调用该命令:
describe('mock calculator add', () => {
  it('shows mocked value', () => {
    cy.mockModule('./calculator', {
      add: () => 10
    })
    cy.visit('http://localhost:5173/')
    cy.get('#app').should('have.text', '10')
  })
})

解决方案二:将模块挂载到window对象(更轻量化)

如果项目允许,可以在应用代码中将模块暴露到全局:

// src/main.ts
import './style.css'
import * as calculator from './calculator'

// 仅在开发/测试环境暴露,避免生产环境污染全局
if (import.meta.env.DEV) {
  (window as any).calculator = calculator
}

document.querySelector<HTMLSpanElement>('#app')!.innerHTML = calculator.add(2, 3).toString()

然后在测试中通过window访问并Stub:

describe('mock calculator add', () => {
  it('shows mocked value', () => {
    cy.visit('http://localhost:5173/', {
      onBeforeLoad(win) {
        cy.stub(win.calculator, 'add').returns(10)
      }
    })
    cy.get('#app').should('have.text', '10')
  })
})

内容的提问来源于stack exchange,提问作者Tomas Baranauskas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 04:15:40