使用Jest模拟嵌套对象时如何使用简写简化测试代码
Jest 嵌套对象Mock的简洁写法
下面提供3种适用不同场景的简写方案:
方案1:一次性字面量赋值
适合嵌套层级不深的场景,直接按对象结构一次性定义,无需逐层赋值:
describe('test cli-request call', () => { it('api injection succeeded', () => { window.api = { cli: { call: jest.fn() } } const mockCmdline = 'whatever'; CLIRequest(mockCmdline); expect(window.api.cli.call).toBeCalledTimes(1); }); })
如果外层属性本身也需要是可监听调用的Mock函数,给对应层级加上jest.fn()即可,示例:
// 若window.api、window.api.cli本身也需要作为函数被调用 window.api = Object.assign(jest.fn(), { cli: Object.assign(jest.fn(), { call: jest.fn() }) })
方案2:用内置jest.mocked实现深度Mock(Jest 27.4及以上版本支持)
适合有TS类型定义的场景,自动带类型提示,第二个参数传true即可开启深度Mock:
// 自动将所有嵌套属性转为Mock函数 window.api = jest.mocked({}, { deep: true }) const mockCmdline = 'whatever'; CLIRequest(mockCmdline); expect(window.api.cli.call).toBeCalledTimes(1);
方案3:自定义通用深度Mock函数
适合嵌套层级很深、不想手动定义每一层结构的场景,用Proxy封装后可无限层级自动生成Mock:
// 提前封装通用工具函数 const createDeepMock = () => new Proxy(jest.fn(), { get(target, prop) { if (Reflect.has(target, prop)) return Reflect.get(target, prop) return target[prop] = createDeepMock() } }) // 业务测试代码仅需一行 window.api = createDeepMock() const mockCmdline = 'whatever'; CLIRequest(mockCmdline); expect(window.api.cli.call).toBeCalledTimes(1);
注意:如果业务逻辑中外层属性仅为普通对象、不需要作为函数被调用,不需要给外层加
jest.fn(),仅给最终需要校验调用的方法加Mock即可,减少不必要的性能开销。
内容的提问来源于stack exchange,提问作者lanxiangc2
相关产品推荐
相关产品推荐

