引言:为什么没有模拟的测试就像无咖啡因的咖啡?
\n\n想象一下:您正在用TypeScript编写一个应用程序,它发送电子邮件、与数据库通信并访问外部API。您运行测试——然后突然全部失败,因为邮件服务器暂时不可用。熟悉吗?
\n\n这时,模拟对象(存根)和测试夹具(测试数据)就登场了。它们可以将代码与外部世界隔离,使测试变得快速、可靠且可预测。在这篇中文文章中,我们将通过真实示例,详细讲解如何正确使用TypeScript中的模拟,有哪些TypeScript测试夹具,以及如何避免踩坑。
\n\n本文为PythonLib编写——这是一个教育门户网站,我们在这里教授如何编写高质量的代码。开始吧!
\n\n什么是模拟对象和测试夹具?
\n\n模拟对象:代码中的替身演员
\n\n模拟对象(简称mock)是真实对象的替代品,它模仿真实对象的行为。您可以说:“当调用sendEmail()方法时,返回true”。这样测试就不会去访问真实的邮件系统。
\n\n在TypeScript中,模拟通常使用Jest或Vitest库创建。它们允许您检查方法是否被调用、使用了哪些参数以及调用了多少次。
\n\n测试夹具:为测试准备的数据
\n\n测试夹具(fixtures)是预先准备好的数据集。例如,用户对象、订单列表或应用程序配置。您无需每次都手动创建它们,而是将测试夹具存储在单独的文件中。
\n\n模拟 + 测试夹具的组合是2024年TypeScript测试的标准做法。
\n\n实践:编写带有模拟和测试夹具的测试
\n\n环境设置
\n\n在示例中,我们将使用Jest(尽管同样的方法也适用于Vitest)。请确保您已安装依赖项:
\n\nnpm install --save-dev jest @types/jest ts-jest\n\n在jest.config.js中添加:
module.exports = {\n preset: 'ts-jest',\n testEnvironment: 'node',\n};\n\n示例1:模拟电子邮件发送服务
\n\n假设我们有一个通知服务:
\n\n// notificationService.ts\nexport class EmailService {\n async sendEmail(to: string, subject: string, body: string): Promise<boolean> {\n // 真实的发送——我们不去动它\n return true;\n }\n}\n\nexport class NotificationManager {\n constructor(private emailService: EmailService) {}\n\n async notifyUser(email: string, message: string): Promise<string> {\n const result = await this.emailService.sendEmail(email, '通知', message);\n return result ? '已发送' : '错误';\n }\n}\n\n现在,我们编写一个带有模拟对象的测试:
\n\n// notificationService.test.ts\nimport { NotificationManager, EmailService } from './notificationService';\n\ndescribe('NotificationManager', () => {\n it('应该发送通知并返回"已发送"', async () => {\n // 创建模拟对象\n const mockEmailService: jest.Mocked<EmailService> = {\n sendEmail: jest.fn().mockResolvedValue(true),\n };\n\n const manager = new NotificationManager(mockEmailService);\n const result = await manager.notifyUser('test@test.com', '你好!');\n\n expect(result).toBe('已发送');\n expect(mockEmailService.sendEmail).toHaveBeenCalledWith(\n 'test@test.com',\n '通知',\n '你好!'\n );\n });\n\n it('如果发送失败,应该返回"错误"', async () => {\n const mockEmailService: jest.Mocked<EmailService> = {\n sendEmail: jest.fn().mockResolvedValue(false),\n };\n\n const manager = new NotificationManager(mockEmailService);