TypeScript中Jest SpyOn可迭代对象报错‘createDiscounts不可迭代’的解决
如何Mock可迭代对象解决‘createDiscounts is not iterable’测试错误
我想为一个简单的TypeScript类监视(spy on)一个普通数组,但运行测试时出现错误提示‘createDiscounts is not iterable’,请问如何mock可迭代对象?
原业务代码(discounts.ts)
// discounts.ts export function createDiscounts() { const discounts: number[] = [0.5, 0.4, 0.7, 0.9] return discounts.entries() } export class ProcessDiscountedItemsService { // 注:原代码中applyDiscounts里的discounts未定义,推测需调用createDiscounts() applyDiscounts = (items: OrderItem) => { for(let [number, discount] of createDiscounts()){ // do logic } } }
测试代码(尝试版)
import * as DiscountUtil from '../discounts.ts' describe('Process discount', () => { const service = new ProcessDiscountedItemsService() it('process item discounts verify', () =>{ const items = /* 你的测试数据 */ const spy = jest.spyOn(DiscountUtil, 'createDiscounts') as jest.Mock const iteratable = [0.5, 0.4, 0.7, 0.9].entries() service.applyDiscounts(items) }) })
问题分析
当前测试代码存在两个核心问题:
- 未给mock的
createDiscounts函数指定返回值,默认返回undefined,而undefined不是可迭代对象,触发错误。 - 原业务代码中
applyDiscounts方法的discounts变量未定义,需修正为调用createDiscounts()获取可迭代对象。
正确Mock方案
方案1:直接返回数组entries迭代器
直接生成符合要求的迭代器作为mock返回值:
import * as DiscountUtil from '../discounts.ts' describe('Process discount', () => { const service = new ProcessDiscountedItemsService() it('process item discounts verify', () =>{ const items = /* 你的测试数据 */ // 创建要mock的可迭代对象 const mockDiscountEntries = [0.1, 0.2].entries() // 监视createDiscounts并指定返回值 const spy = jest.spyOn(DiscountUtil, 'createDiscounts') as jest.Mock spy.mockReturnValue(mockDiscountEntries) // 执行测试方法 service.applyDiscounts(items) // 验证函数调用(可选) expect(spy).toHaveBeenCalled() }) })
方案2:手动实现可迭代对象
如果需要自定义迭代逻辑,可手动实现带有[Symbol.iterator]方法的可迭代对象:
import * as DiscountUtil from '../discounts.ts' describe('Process discount', () => { const service = new ProcessDiscountedItemsService() it('process item discounts verify', () =>{ const items = /* 你的测试数据 */ // 手动创建可迭代对象 const mockIterable = { [Symbol.iterator]: function* () { yield [0, 0.1] yield [1, 0.2] } } // 监视并返回自定义可迭代对象 const spy = jest.spyOn(DiscountUtil, 'createDiscounts') as jest.Mock spy.mockReturnValue(mockIterable) service.applyDiscounts(items) expect(spy).toHaveBeenCalled() }) })
业务代码修正
需将原业务代码中未定义的discounts变量修正为调用createDiscounts():
applyDiscounts = (items: OrderItem) => { const discounts = createDiscounts() for(let [number, discount] of discounts){ // do logic } }
内容的提问来源于stack exchange,提问作者BreenDeen
相关产品推荐
相关产品推荐

