Mock Generator函数的核心是拦截并控制其执行过程,重点mock next()返回的{value, done}对象(尤其value常为Promise),而非Generator本身;需适配运行环境如redux-saga(用testSaga断言yield)或co(mock底层异步依赖),现代推荐改用async/await简化测试。

在单元测试中 Mock Generator 函数,核心不是“替换生成器本身”,而是拦截并控制它的执行过程——尤其是它产出的 Promise 或异步行为。Generator 本身不执行异步操作,真正触发异步的是你用 next() 驱动它时返回的值(比如 { value: Promise, done: false }),以及后续如何处理这个 value(例如被 co、redux-saga 或自定义 runner 消费)。
Mock 生成器的返回值(value),而非生成器函数本身
直接 spyOn 或 jest.mock 一个 generator 函数没意义,因为它返回的是迭代器对象。你需要 mock 的是迭代器 next() 方法返回的对象,特别是其中的 value 字段(常为 Promise)。
- 用
jest.fn()手动构造一个模拟迭代器,让它的next返回预设的 { value, done }:
const mockIterator = {
next: jest.fn()
.mockReturnValueOnce({ value: Promise.resolve(1), done: false })
.mockReturnValueOnce({ value: Promise.resolve(2), done: false })
.mockReturnValueOnce({ value: undefined, done: true })
};
- 如果被测代码调用
genFn().next(),就可提前注入这个 mock 迭代器(例如通过依赖注入、工厂函数或模块 mock)。
针对常见运行环境做适配(如 redux-saga、co)
Generator 很少裸用,多数由运行时库驱动。Mock 策略需匹配其消费方式:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
redux-saga:用
testSaga(来自redux-saga-test-plan)直接断言 yield 内容,无需手动 mock Promise:
import { testSaga } from 'redux-saga-test-plan';
import { call, put } from 'redux-saga/effects';
import { fetchData } from './sagas';
test('fetchData saga yields correct calls', () => {
testSaga(fetchData)
.next() // 启动
.call(fetch, '/api/data') // 断言第一个 yield 是 call(fetch, ...)
.next({ data: 'ok' }) // 模拟 fetch 返回值
.put({ type: 'FETCH_SUCCESS', payload: 'ok' });
});
-
co 或自定义 runner:Mock runner 调用的底层方法(如
fetch、axios.get),让它们返回可控 Promise;runner 自动处理 yield 后的 resolve/reject,你只需验证最终状态或副作用。
用 async/await + yield 替代 Generator(现代推荐)
ES2017+ 后,绝大多数场景可用 async function 替代 Generator + runner 组合。它更直观、调试友好、且单元测试更简单:
立即学习“Java免费学习笔记(深入)”;
- 直接 mock 异步依赖(如
jest.mock('./api', () => ({ getData: jest.fn() }))) - 用
await调用被测函数,断言返回值或 mock 调用次数 - 无需关心迭代器、done、value 等中间态,逻辑验证聚焦在输入输出和副作用上
避免踩坑:别 mock 迭代器的 Symbol.iterator
不要试图 mock [Symbol.iterator] 方法来“劫持 for...of”,这会让测试耦合实现细节,且难以覆盖 next() 的多次调用路径。专注 mock next() 的返回值,或更高层的异步依赖,才是稳定可靠的策略。

















