the-only-3-steps-you-need-to-mock-an-api-call-in-jest-39mb

原始地址:https://dev.to/zaklaughton/the-only-3-steps-you-need-to-mock-an-api-call-in-jest-39mb

我最近在一个Javascript代码库中工作,我需要实现新的Jest测试。当时我对编写测试知之甚少,所以我查看了Jest文档和代码库中现有的模式,找出了最佳实践和实现方法。这是相当直观的,我甚至发现自己喜欢上了测试。但是我却一直无法可靠地模拟API调用。
文档似乎很明确,现有的代码似乎有良好的模式,但是有太多种方法可以模拟事物。现有的测试使用了各种各样的模拟方法,如jest.genMockFromModule()、jest.spyOn()和jest.mock()。有时,模拟是内联的,有时在变量中,有时从神秘的__mocks__文件夹中以神奇的方式导入和导出。我每次在理解时都可以互换使用这些技术,结果发现自己在不同的方法和效果之间摇摆不定。我不知道自己在做什么。

点击查看原文
问题
问题在于我试图在还不知道如何走之前就学会奔跑。Jest有许多强大的方法可以模拟函数并优化这些模拟,但是如果您不知道如何首先创建一个简单的模拟,这些方法都是无用的。虽然Jest文档提供了许多很好的见解和技术,但是我无法弄清楚从哪里开始
在本文中,我希望为您提供模拟API调用的绝对基础知识,以便您可以从我的经验中受益(2020年)。如果您像我一样疯狂,因为您无法理解如何仅仅制作一个简单的模拟,请从这里开始…(注意:下面的代码是使用Node.js编写的,但是模拟概念也适用于前端JavaScript和ES6模块)

点击查看原文
未模拟的代码
我们将测试这个
getFirstAlbumTitle()函数,该函数从API获取一个专辑数组,并返回第一个专辑的标题:
// index.js
const axios = require(‘axios’);
async function getFirstAlbumTitle() {
const response = await axios.get(‘https://jsonplaceholder.typicode.com/albums’);
return response.data[0].title;
}
module.exports = getFirstAlbumTitle;
… 这是我们为这个函数编写的初始无模拟测试,它验证函数是否实际返回列表中第一个专辑的标题:
// index.test.js
const getFirstAlbumTitle = require(‘./index’);
it(‘returns the title of the first album’, async () => {
const title = await getFirstAlbumTitle(); // 运行函数
expect(title).toEqual(‘quidem molestiae enim’); // 对结果进行断言
});
上述测试完成了它的工作,但是当运行时,测试实际上会向API进行网络请求。如果API的工作方式与预期不符(例如,列表顺序改变、API不可用、开发机器失去网络连接等),这会导致各种错误的结果。更不用说在大量测试中进行这些请求会导致测试运行变得非常缓慢。
但是我们如何改变呢?API请求是作为
getFirstAlbumTitle()的一部分使用axios执行的。我们如何达到
函数内部并更改其行为呢?

点击查看原文
三步模拟
好了,这就是它。这是一个重要的秘密,如果我在学习模拟时能知道这个秘密,我将节省大量的时间。要在函数中模拟API调用,您只需要执行以下3个步骤:
1. 导入要模拟的模块到您的测试文件中。 2.
使用jest.mock()模拟该模块。
3. 使用
.mockResolvedValue(<模拟的响应>)来模拟响应。
就是这样!
在这样做后,我们的测试看起来像是这样:
// index.test.js
const getFirstAlbumTitle = require(‘./index’);
const axios = require(‘axios’);
jest.mock(‘axios’);
it(‘returns the title of the first album’, async () => {
axios.get.mockResolvedValue({
data: [
{
userId: 1,
id: 1,
title: ‘My First Album’
},
{
userId: 1,
id: 2,
title: ‘Album: The Sequel’
}
]
});
const title = await getFirstAlbumTitle();
expect(title).toEqual(‘My First Album’);
});

点击查看原文
这里发生了什么?
让我们分解一下。理解这里最重要的部分是导入和
jest.mock():
const axios = require(‘axios’);
jest.mock(‘axios’);
当您将一个模块导入到测试文件中,然后在
jest.mock()中呼叫它时,您完全控制了该模块中的所有函数,即使它们在另一个导入的函数中调用。在调用
jest.mock(‘axios’)之后,Jest将该模块中的每个函数都替换为空的"mock"函数,这些函数实际上什么都不做并返回
undefined:
const axios = require(‘axios’);
jest.mock(‘axios’)
// 什么都不做,然后返回undefined:
axios.get(‘https://www.google.com’)
// 什么都不做,然后返回undefined:
axios.post(‘https://jsonplaceholder.typicode.com/albums’, {
id: 3,
title: ‘Album with a Vengeance’
})
现在,您已经消除了默认行为,可以用自己的行为替换它…
axios.get.mockResolvedValue({
data: [
{
userId: 1,
id: 1,
title: ‘My First Album’
},
{
userId: 1,
id: 2,
title: ‘Album: The Sequel’
}
]
});
Jest插入到
axios 中的模拟替换函数恰好具有许多强大的超能力方法来控制它们的行为!对于一个简单的初学者模拟来说,其中最重要的一个是
.mockResolvedValue()。当您在一个模拟的方法上调用它时,您传入的任何内容都将是测试的其余部分调用模拟函数时的默认返回值。简而言之,可以使
axios.get() 返回您想要的任何内容!而且
不管它是直接在您的测试文件中调用还是作为一个导入到您的测试中的函数的一部分,无论其在何处调用,Jest都会模拟该函数!
利用这种新的能力,准确提供给您的函数从API调用中应该期望的内容。不再担心网络请求返回的内容,只需关注您的代码在收到响应后做什么即可!
如果您想尝试这些示例,请随意使用此演示存储库:

ZakLaughton / simple-api-mocking-with-jest

一个使用Jest进行简单API模拟的示例。

点击查看原文
总结
就是这样!这是模拟来自另一个模块的函数所需的非常基础的知识:
导入模块,使用jest.mock()模拟模块,然后使用.mockResolvedValue()插入自己的返回值!
我建议从这里开始,只使用这些技术来构建您的网络调用的第一个模拟。一旦您对这里发生的情况有了基本的理解,您可以逐步开始添加在Jest中包含的其他强大的模拟功能。另请参阅:模拟模块(Jest文档)。 编辑: 另外,请确保在每个测试之间清除模拟,通过运行jest.resetAllMocks() 。这将有助于确保您的模拟不会干扰未来的测试。(感谢mjeffe指出这一点!)

点击查看原文
接下来去哪里
好的,您已经学会了模拟的基础知识,并成功在多个测试中实现了上述策略。您可以像老手一样轻松导入和模拟解决值。接下来呢?
虽然上述方法可以满足大多数简单用例,但是Jest提供了许多模拟功能和方法,可以实现一些非常强大的功能。您可以逐步使用下面的概念来增强您的模拟:

  • 查看Jest文档中列出的其他模拟函数方法:Mock Functions。您可以使用方法如
    mockReturnedValue()来模拟同步返回,使用
    mockResolvedValueOnce()仅在第一次调用时返回值。
  • 想知道模拟函数被调用了多少次,它被调用时的参数是什么,以及它返回了什么?查看
    mock.calls和
    mock.results属性(也在模拟函数文档中)
  • 您有自己的自定义函数执行网络请求吗?当它们导入到测试文件后,您也可以对您自己的模块进行模拟:
    jest.mock(‘./path/to/js/module/file’)!请注意,这里仅模拟必要的部分。您的测试应该确保您的函数在给定模拟输入的情况下是否按预期工作,而很容易编写仅确认是否传入了模拟数据的测试。
  • 想要一个函数像其原始编写的方式一样运行,但仍想知道它被调用了多少次?请查看
    jest.spyOn()
  • 发现自己在多个测试中一遍又一遍地模拟同一个函数?在
    __mocks__文件夹中使用默认模拟响应给它们,使用
    手动模拟
    我希望这篇文章能为其他人节省一些浪费的时间和沮丧。如果这里有任何事情让人不理解,请留下评论,我将很乐意尝试回答任何问题。另外,请告诉我还有其他什么东西帮助您在学习模拟时有一个“Aha!”的时刻!
    您觉得本文章有用吗?请随意订阅我的下面的文章或
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值