拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

使用 Jest mockReturnValue 为 Mock 函数注入返回值——TIL 项目 JavaScript 实战笔记

使用 Jest mockReturnValue 为 Mock 函数注入返回值——TIL 项目 JavaScript 实战笔记
  • 文档
  • 教程
  • 知识库

【免费下载链接】til

:memo: Today I Learned

项目地址:https://gitcode.com/gh_mirrors/ti/til
点击查看免费下载

本篇技术指南聚焦 TIL 仓库 javascript/mock-a-function-with-return-values-using-jest 所记录的核心技巧:如何用jest.fn()创建 Mock 函数,并通过mockReturnValue()/mockReturnValueOnce()为它注入固定或一次性返回值,从而让被测代码在无需真实依赖的情况下稳定运行。读完本文,你将掌握 Mock 函数从创建、赋值、注入返回值到落地到组件测试与定时器测试的完整链路,并了解它与mockImplementation、mockResolvedValue等姊妹 API 的关系。

一、起步:用 jest.fn() 创建 Mock 函数

Jest 为处理 Mock 函数提供了一整套工具集合(Mock Function API),其中最基础的入口就是jest.fn()。调用它即可得到一个全新的 Mock 函数,该函数本身不执行任何业务逻辑,而是由测试代码按需配置其行为。

jest.fn() // 赋值给一个变量 const fakeFunc = jest.fn(); // 作为 prop 传给组件 <SpecialInput handleChange={jest.fn()} />

从上面的三行代码可以看到jest.fn()的三种典型用法:

  1. 直接调用:生成一个未绑定的 Mock 函数实例;
  2. 赋值给变量:将 Mock 函数保存为fakeFunc,后续可以通过该变量统一配置返回值、调用次数等行为;
  3. 作为 prop 传入组件:在渲染组件时传入一个 Mock 函数(如上面的handleChange),用于占位并观测组件是否正确调用了该回调。

这一点在 TIL 仓库的 react/mock-a-function-that-a-component-imports 中有直接的印证——当组件依赖一个导入的函数isAuthenticated()时,测试中正是用jest.fn().mockReturnValue(true)来替换真实实现;而在 xstate/custom-jest-matcher-for-xstate-machine-states 中,XState 机器的action: jest.fn()同样以 Mock 函数来观测动作是否被触发。

二、mockReturnValue():让 Mock 函数始终返回指定值

创建出 Mock 函数之后,下一步就是为它配置返回值。最常用的方法是mockReturnValue(value):

const fakeFunc = jest.fn(); fakeFunc.mockReturnValue("hello"); fakeFunc(); // => "hello"

mockReturnValue()的核心语义是:无论函数被调用多少次,只要没有更优先的一次性配置,它都会返回同一个值。在上述示例中,fakeFunc每次被调用都会得到字符串"hello",测试代码无需关心函数内部逻辑,只需确认"当这个函数被调用时,它会返回什么",这正是单元测试隔离外部依赖的关键手法。

这种"恒定返回值"在真实测试场景中极其常用。TIL 仓库的 react/mock-a-function-that-a-component-imports 给出了一个完整的落地案例:

// MyComponent.test.js // ... various testing imports import * as authModules from './authentication'; it('renders the component', () => { authModules.isAuthenticated = jest.fn().mockReturnValue(true); const wrapper = shallow(<MyComponent />); expect(toJson(wrapper)).toMatchSnapshot(); });

这里通过import * as authModules拿到与MyComponent相同的模块引用,把isAuthenticated替换为jest.fn().mockReturnValue(true)的 Mock 版本。于是渲染MyComponent时,组件内部调用到的isAuthenticated()会返回true,从而走入"已认证"分支,测试无需真实登录态。反向场景只需要把返回值换成false:

authModules.isAuthenticated = jest.fn().mockReturnValue(false);

一句话总结:mockReturnValue()的价值在于"凡调用,必返回",让依赖方在固定前提下被稳定驱动。

三、mockReturnValueOnce():让返回值只生效一次

与mockReturnValue()相对,mockReturnValueOnce(value)只让指定返回值生效一次,随后的调用不再返回该值:

const fakeFunc = jest.fn(); fakeFunc.mockReturnValueOnce("hello"); fakeFunc(); // => "hello" fakeFunc(); // => null

mockReturnValueOnce()的语义是"第一次调用时返回配置值,之后回落到 Mock 函数的默认行为"。这里有一个容易被忽略的细节需要澄清:在 Jest 中,未配置任何返回值/实现的 Mock 函数,其默认调用结果实际上是undefined,而不是null;原始笔记以null概括"此后不再返回任何配置值"这一结果,读者理解其意图即可,在编写断言时请以实际默认值undefined为准。

该 API 最典型的用途是模拟"前几次调用返回特殊值"的场景,例如:

  • 模拟轮询接口:第一次返回"处理中",后续返回"已完成";
  • 模拟数据库查询:某次查询命中缓存返回 A,其余返回 B;
  • 模拟需要多次调用才稳定的第三方 SDK。

四、组合运用:默认返回值 + 一次性覆盖

mockReturnValue()与mockReturnValueOnce()并不互斥,二者组合可以表达"大部分调用返回默认值,仅某几次调用返回特殊值"的行为:

const fakeFunc = jest.fn(); fakeFunc .mockReturnValue("default") .mockReturnValueOnce("first") .mockReturnValueOnce("second"); fakeFunc(); // => "first" fakeFunc(); // => "second" fakeFunc(); // => "default" fakeFunc(); // => "default"

组合时的优先级规则是:一次性配置(Once系列)总是先于永久配置(mockReturnValue系列)被消费。所有Once值按注册顺序依次消耗完毕后,函数才回落到mockReturnValue设置的恒定值。这一规则让"先特殊、后通用"的测试编排变得非常直观。

五、仓库实例:Mock 函数在定时器与日志测试中的落地

除了注入返回值,jest.fn()的调用记录能力也是断言的核心依据。TIL 仓库的 javascript/test-timing-based-code-with-jest-fake-timers 展示了jest.fn()与假定时器配合、用toHaveBeenCalled()验证调用是否发生的完整流程:

jest.useFakeTimers(); describe("doSomethingAfter200ms", () => { test("does something after 200ms (pass)", () => { const doSomething = jest.fn(); doSomethingAfter200ms(doSomething); jest.advanceTimersByTime(201); expect(doSomething).toHaveBeenCalled(); }); });

这里doSomething无需关心返回值——Mock 函数同时具备"可配置行为"与"可观测调用历史"两种能力。类似的模式还出现在 javascript/turn-off-console-error-messages-in-a-test 中,通过console.error = jest.fn()屏蔽测试期的噪音输出。结合这两个仓库实例可以得出:jest.fn()是"注入返回值 + 记录调用历史"的统一入口,而mockReturnValue只是它众多行为配置中的一支。

六、延伸:mockReturnValue 的姊妹 API

mockReturnValue与mockReturnValueOnce属于 Jest Mock Function API 家族,理解它们后可以顺带掌握同族的其他常用成员,它们共享"永久/一次性"与"普通值/异步值"两对维度的组合逻辑:

API语义
mockReturnValue(value)每次调用都返回该值(本文主题)
mockReturnValueOnce(value)仅下一次调用返回该值(本文主题)
mockImplementation(fn)用自定义函数完全接管 Mock 函数的行为
mockImplementationOnce(fn)仅下一次调用使用自定义实现
mockResolvedValue(value)等价于mockImplementation(() => Promise.resolve(value)),用于返回已兑现的 Promise
mockResolvedValueOnce(value)仅下一次调用返回已兑现的 Promise
mockRejectedValue(value)等价于mockImplementation(() => Promise.reject(value)),用于模拟异步失败

选择建议:当被测代码只需要"知道返回值"时,优先用mockReturnValue系列(更简洁);当需要模拟真实逻辑或异步行为时,再考虑mockImplementation与mockResolvedValue系列。配合toHaveBeenCalled()、toHaveReturnedWith(value)等断言,即可对"返回值是否被正确注入、调用是否发生"做完整的双向验证。

小结

围绕 TIL 仓库 javascript/mock-a-function-with-return-values-using-jest 这篇笔记,本文完整覆盖了jest.fn()创建 Mock 函数的三种方式、mockReturnValue()的恒定返回值语义、mockReturnValueOnce()的一次性语义及"回落后返回undefined"的细节,并补充了二者组合时的优先级规则。结合仓库中 react/mock-a-function-that-a-component-imports、javascript/test-timing-based-code-with-jest-fake-timers 与 javascript/turn-off-console-error-messages-in-a-test 的实战样例可以看到:注入返回值只是 Mock 函数能力的入口,配合调用历史断言与一次性覆盖,足以支撑绝大多数前端与 Node 侧单元测试场景。

  • 文档
  • 教程
  • 知识库

【免费下载链接】til

:memo: Today I Learned

项目地址:https://gitcode.com/gh_mirrors/ti/til
点击查看免费下载
上一篇:Austin项目实战指南
下一篇:Anima开源项目使用教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表