Jest 非常擅长在 javascript/typescript 中模拟导入,但我发现很难记住实现细节。
函数和对象需要以不同的方式进行模拟,默认导出的模拟与命名导出略有不同,并且 Jest 与打字稿的配合效果不佳。将所有这些事情结合起来,可能很难找出甚至搜索适合您的模拟场景的正确方法。
我创建本指南是为了回答这个问题“如何模拟我的导入?”无论导入是什么。默认或命名、函数或对象。
我的环境
我已经使用以下版本的软件测试了所有这些方法:
- 节点 v22.11.0
- 笑话 v29.7.0
- ts-jest v29.2.5
- @types/jest v29.5.14
使用默认的最小 jest.config.js 文件:
export default { testEnvironment: 'node', transform: { '^.+.tsx?$': ['ts-jest', {}], }, testMatch: ['**/*.test.ts'], };
模拟导入
广泛常见的导入分为我们可能想要模拟的两类:
- 功能
- 物体
我们将从函数开始依次解决这两个问题。
导入函数
从模块导出的函数可以命名或默认。我们会看看两者。第一:
模拟模块中的命名导出函数
这应该用于模拟模块中的命名导出函数,如下所示:
// ./path/to/module.ts export function doSomething(...) { ... }
可以像这样嘲笑:
import { doSomething } from './path/to/module'; // note: This should be the path to the module from the test file, // NOT from the module that contains the doSomething function itself. jest.mock('./path/to/module', () => ({ doSomething: jest.fn(), })); ... it('should do something', () => { // We need to assert that the function is a jest.Mock // so that typescript will allow us to call mock methods. (doSomething as jest.Mock).mockReturnValue(mockValue); // run your test here expect(doSomething).toHaveBeenCalledTimes(1); // etc. });
模拟从模块返回的默认函数
这应该用于模拟模块默认导出的函数,如下所示:
// ./path/to/module.ts export default function doSomething(...) { ... }
它的模拟方式与命名导出类似:
import doSomething from './path/to/module' jest.mock('./path/to/module', () => ({ __esModule: true, default: jest.fn() })) ... it('should do something', () => { (doSomething as jest.Mock).mockResolvedValue(mockData); // Run your test here expect(doSomething).toHaveBeenCalledTimes(5); });
导入对象
模拟导出的对象(可以是类、json 对象或其他对象)时需要考虑一些变化。
- 它是命名导出还是默认导出?
- 它是否有我们也希望模拟的方法,或者只是属性?
没有方法的模拟默认对象
如果您只需要模拟属性(例如配置文件),而不是方法,那么具体做法如下:
import config from '../config'; jest.mock('../config', () => ({ __esModule: true, default: { apiKey: '123MockKey', ... }, })); ... it('Should do something', () => { ... });
如果每次测试需要改变模拟属性:
import config from '../config'; const mockConfig = { apiKey: '123MockKey', ... }; jest.mock('../config', () => ({ __esModule: true, default: mockConfig, })); ... beforeEach(() => { // restore defaults before each test mockConfig.apiKey = '123MockKey'; ... }); it('Should do something', () => { mockConfig.apiKey = 'new value'; // rest of the test }); // more tests
模拟没有方法的命名导出对象
与模拟默认导出对象非常相似:
import { config } from '../config'; const mockConfig = { apiKey: '123MockKey', ... }; jest.mock('../config', () => ({ config: mockConfig, })); // the rest is exactly the same as when mocking a default export object.
使用方法模拟对象
当从模块导出(命名或默认)带有方法的对象时,我们需要模拟这些方法的输出,方法略有不同。
上课:
// ./path/to/module.ts class ComplicatedThing { // properties, fields, constructor etc. go here getData() { ... } ... } // note: I don't necessarily recommend exporting an instance // of a class like this - purely illustrative for testing purposes. // https://medium.com/@lazlojuly/are-node-js-modules-singletons-764ae97519af export const complicatedThing = new ComplicatedThing(...);
并模拟我们导出的对象:
export default { testEnvironment: 'node', transform: { '^.+.tsx?$': ['ts-jest', {}], }, testMatch: ['**/*.test.ts'], };
模拟默认导出对象是完全相同的,除了我们定义模拟时:
// ./path/to/module.ts export function doSomething(...) { ... }
奖励:模拟对象上的方法作为参数直接传递给测试函数/类
这是为了模拟一个对象,该对象不是直接导入到您正在测试的模块中,而是作为参数传递给类/函数。
注意:如果您正在模拟一个类,您可能希望创建一个接口并创建该接口的模拟实现以传递到您的函数/类中。这将使您无需进行如下不优雅的类型断言恶作剧。
import { doSomething } from './path/to/module'; // note: This should be the path to the module from the test file, // NOT from the module that contains the doSomething function itself. jest.mock('./path/to/module', () => ({ doSomething: jest.fn(), })); ... it('should do something', () => { // We need to assert that the function is a jest.Mock // so that typescript will allow us to call mock methods. (doSomething as jest.Mock).mockReturnValue(mockValue); // run your test here expect(doSomething).toHaveBeenCalledTimes(1); // etc. });
// ./path/to/module.ts export default function doSomething(...) { ... }
import doSomething from './path/to/module' jest.mock('./path/to/module', () => ({ __esModule: true, default: jest.fn() })) ... it('should do something', () => { (doSomething as jest.Mock).mockResolvedValue(mockData); // Run your test here expect(doSomething).toHaveBeenCalledTimes(5); });
结论
我希望这对你有用,也对我未来的自己有用,当我下次努力记住如何在打字稿中模拟导入的细节时。
我希望它能够满足您所有简单的模拟需求,并为您在模拟更复杂的导入时提供一个起点。
感谢您的阅读。
以上是用 Jest 和 typescript 进行嘲笑 - 备忘单的详细内容。更多信息请关注PHP中文网其他相关文章!

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Atom编辑器mac版下载
最流行的的开源编辑器

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境