在前端开发中,我们经常需要对函数进行测试。Jest 是一个非常流行的 JavaScript 测试框架,而 Sinon 则是一个强大的 JavaScript 测试工具库,可以让我们在测试中模拟函数行为以及处理异步操作。本文将介绍如何在 Jest 中使用 Sinon 来模拟函数行为。
安装 Jest 和 Sinon
在开始之前,我们需要先安装 Jest 和 Sinon。可以使用 npm 进行安装:
npm install --save-dev jest sinon
模拟函数行为
Stub
Sinon 中有一个 stub 方法,可以用来替换一个函数并且完全控制它的行为。假设我们有一个名为 getUsername
的函数,它需要调用一个 API 来获取用户的用户名:
async function getUsername(userId) { const response = await fetch(`https://api.example.com/users/${userId}`); const data = await response.json(); return data.username; }
为了避免在测试中真正地调用 API,我们可以使用 Sinon 的 stub 方法来模拟 fetch
方法的行为:
-- -------------------- ---- ------- ----- ----- - ----------------- ----------------- ------ ------ --- ------- ---------- ----- -- -- - ----- ---- - ------------------ --------- ----------------------------------------------------------- ----- -- -- ----------------- --------- --------- --- --- ----- -------- - ----- --------------- --------------------------------- --------------- ---
上面的代码中,我们使用 sinon.stub
方法创建了一个名为 stub
的 stub 对象。然后,我们使用 stub.withArgs
方法配置了当调用 fetch('https://api.example.com/users/1')
时,返回的对象应该是一个具有 json
方法的对象。
最后,我们在测试用例中调用 getUsername
方法,可以看到它直接返回了我们预期的用户名。
Mock
另一个很有用的 Sinon 方法是 mock。它与 stub 类似,但可以在期望时验证调用次数。
假设我们有一个名为 saveUser
的函数,它需要将用户数据发送到 API:
async function saveUser(userData) { const response = await fetch('https://api.example.com/users', { method: 'POST', body: userData, }); const data = await response.json(); return data.success; }
为了验证 saveUser
函数是否正确地将用户数据发送到 API,我们可以使用 Sinon 的 mock 方法来模拟 fetch
方法的行为,并使用 expect
验证它被调用了一次:
-- -------------------- ---- ------- ----- ----- - ----------------- -------------- ------ ---- ---- ---- -- --- ----- ----- -- -- - ----- ---- - ------------------- ---------------------------------------------------------------------- - ------- ------- ----- ---------------- ----- ----- ----- ------ --------------------- --- ---------------------------- ----- -- -- ----------------- -------- ---- --- ---- ----- ------ - ----- ---------- ----- ----- ----- ------ --------------------- --- -------------------------- -------------- --------------- ---
上面的代码中,我们使用 sinon.mock
方法创建了一个名为 mock
的 mock 对象。然后,我们使用 mock.expects
方法配置了当调用 fetch
方法时,期望它被调用一次,并且带有正确的参数。最后,我们使用 mock.verify
方法进行验证。
处理异步操作
在测试中,我们经常需要处理异步操作,比如 API 调用或者 DOM 事件。Sinon 提供了一些方法来帮助我们处理异步操作。
Fake timers
Sinon 提供了一个 fakeTimers 对象,可以用来模拟 setTimeout、setInterval 和 Date 等异步操作。假设我们有一个名为 delayedGreeting
的函数,它会在两秒后显示一个问候信息:
function delayedGreeting() { setTimeout(() => { console.log('Hello world!'); }, 2000); }
为了在测试中避免等待两秒钟,我们可以使用 Sinon 的 fakeTimers 对象,并使用 tick
方法来模拟时间的前进:
-- -------------------- ---- ------- ----- ----- - ----------------- --------------------- ------ --- - -------- ----- --- --------- -- -- - ----- ----- - ---------------------- ----- ---------- - ------------------- ------- ------------------ ----------------- ---------------------------------------------- --------- ------------------------- ---------------- ---
上面的代码中,我们使用 sinon.useFakeTimers
方法创建了一个名为 clock
的 fakeTimers 对象。然后,我们使用 jest.spyOn
方法来监视 console.log
方法的调用。接着,我们调用 delayedGreeting
方法,并使用 clock.tick
方法前进了两秒钟。最后,我们使用 expect
验证 console.log
方法被调用,并打印了正确的问候信息。
Fake XHR
Sinon 还提供了一个 fakeXHR 对象,用来模拟 XMLHttpRequest 对象。假设我们有一个名为 fetchData
的函数,它会调用一个 API 并返回相应数据:
-- -------------------- ---- ------- ----- -------- ----------- - ----- --- - --- ----------------- --------------- -------------------------------- --- ----- ---------------------- - -- -- - -- --------------- --- - -- ---------- --- ---- - ---- - ----------------------------- - -- ----------- ----- ------- - -- ------- --- ------- ----- --- --------------- -- ------------------- ----- - ------ ----- -
为了在测试中避免真正地调用 API,我们可以使用 Sinon 的 fakeXHR 对象,并使用 useFakeXMLHttpRequest
方法将它注册到全局对象中:
-- -------------------- ---- ------- ----- ----- - ----------------- --------------- ------ ------ --- ------- ------ ----- -- -- - ----- ------- - ------------------------------ ----- ---- - -- --- -- ----- ----- ---- -- - --- -- ----- ----- ---- --- -------------------------- ------------------------------- - ---- - --------------- ------------------ -- -------------------- --- ----- ------ - ----- ------------ ----------------------------- ------------------ ---
上面的代码中,我们使用 sinon.useFakeXMLHttpRequest
方法创建了一个名为 fakeXhr
的 fakeXHR 对象,并使用 respondWith
方法配置了当调用 xhr.open('GET', 'https://api.example.com/data')
时,返回的数据应该是一个具有正确内容类型和正确数据的对象。
最后,我们在测试用例中调用 fetchData
方法,可以看到它直接返回了我们预期的数据。
结论
通过使用 Sinon,我们可以在 Jest 中模拟函数行为,并且处理异步操作。这样,我们可以更好地控制测试环境,提高测试质量并加快测试速度。如果你想深入学习 Sinon 的更多功能,建议访问其官方文档进行探索。
示例代码
完整的示例代码可以在 GitHub 上的仓库中找到:https://github.com/yourgithubusername/jest-sinon-example/
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/66efefcb6fbf96019731616e