使用 Jest 模拟 ES6 类方法!
先决条件
先决条件
在开始本教程之前,我假设你已经有一个正在开发的 JavaScript 项目,并且已经了解一些关于测试的基础知识以及编写测试的原因。听起来有点熟悉?太好了,让我们开始吧!
我们为什么要嘲讽?
编写单元测试时,务必隔离当前测试的特定组件(或单元)。如果隔离得不够有效,就可能测试到目标代码之外的其他部分。为了避免这种情况,我们可以模拟代码的外部部分,以模拟代码可能运行的特定环境。这样可以确保代码在不同条件下始终按预期运行。
以玩笑嘲讽
幸运的是,Jest 让模拟代码的不同部分变得相当简单(一旦你弄清楚它是如何实现的)。接下来,我将介绍几种我们目前可以使用的基本方法!
设置
我假设我们有两个类。一个是“ProductManager”类,这是我们目前正在测试的类;另一个是“ProductClient”类,用于从 API 获取产品。
ProductsClient 可能类似于以下示例。
export class ProductsClient {
async getById(id) {
const url = `http://localhost:3000/api/products/{id}`;
const response = await fetch(url);
return await response.json();
}
}
产品经理的界面可能看起来像这样。
export class ProductManager {
async getProductToManage(id) {
const productsClient = new ProductsClient();
const productToManage = await productsClient.getById(id)
.catch(err => alert(err));
return productToManage;
}
}
所以,ProductManager 会获取产品并返回其值,如果获取过程中出现错误,则会发出警报。看起来很简单,对吧?好的,让我们看看如何使用 Jest 模拟 ProductsClient 来对 ProductManager 进行单元测试。
编写测试
我要展示的第一种方法是使用 Jest 的自动模拟功能。只需导入要模拟的模块,然后调用 jest.mock(),就像这样。
import { ProductsClient } from './ProductsClient';
jest.mock('./ProductsClient');
现在,ProductsClient 类中的所有方法(例如 getById())都会被自动模拟并返回 'undefined'。这对于很多应用场景来说可能完全没问题。但对于我们的情况来说,这存在一些问题。首先,如果 ProductClient 始终返回 'undefined',我们如何测试 ProductManager 是否返回了正确的值?更重要的是,如果调用 getById() 返回 'undefined',我们的 .catch() 语句会抛出错误,因为我们无法对 'undefined' 调用方法!
嘲笑我们的回报价值
那么,我们该如何解决这个问题呢?我们可以模拟函数的返回值。假设我们现有的测试用例如下所示。
it('should return the product', async () => {
const expectedProduct = {
id: 1,
name: 'football',
};
const productManager = new ProductManager();
const result = await productManager.getProductToManage(1); // Will throw error!
expect(result.name).toBe('football');
});
我们需要确保在 ProductManager 类中调用 ProductClient 的 `getById` 方法时返回一个解析为 `expectedProduct` 的 Promise。为此,我们需要将一个模拟函数赋值给 ProductClient 的 `getById` 方法。然而,由于我们使用的是 ES6 类语法,所以不能简单地将其赋值给 `ProductsClient.getById`,而是需要将其赋值给对象的原型。
const mockGetById = jest.fn();
ProductsClient.prototype.getById = mockGetById;
完成这一步后,我们就可以添加模拟函数应该返回的内容了。
const mockGetById = jest.fn();
ProductsClient.prototype.getById = mockGetById;
mockGetById.mockReturnValue(Promise.resolve(expectedProduct));
现在我们完成的测试文件应该如下所示。
import { ProductsClient } from './ProductsClient';
import { ProductManager } from './ProductManager';
jest.mock('./ProductsClient');
it('should return the product', async () => {
const expectedProduct = {
id: 1,
name: 'football',
};
const productManager = new ProductManager();
const mockGetById = jest.fn();
ProductsClient.prototype.getById = mockGetById;
mockGetById.mockReturnValue(Promise.resolve(expectedProduct));
const result = await productManager.getProductToManage(1);
expect(result.name).toBe('football'); // It passes!
});
结论
希望这篇文章能帮助你更好地了解如何使用 Jest 模拟类方法!如果你喜欢这篇文章,欢迎留言分享你的想法和建议,告诉我你还想看到哪些其他内容。感谢阅读!
文章来源:https://dev.to/jackcaldwell/mocking-es6-class-methods-with-jest-bd7