TypeScript测试中的模拟对象和测试夹具:从新手到专家

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么没有模拟的测试就像无咖啡因的咖啡?

\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\n
npm install --save-dev jest @types/jest ts-jest
\n\n

在jest.config.js中添加:

\n\n
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);                

博客

书籍推荐