Jest 中使用 Sinon 模拟函数行为

阅读时长 9 分钟读完

在前端开发中,我们经常需要对函数进行测试。Jest 是一个非常流行的 JavaScript 测试框架,而 Sinon 则是一个强大的 JavaScript 测试工具库,可以让我们在测试中模拟函数行为以及处理异步操作。本文将介绍如何在 Jest 中使用 Sinon 来模拟函数行为。

安装 Jest 和 Sinon

在开始之前,我们需要先安装 Jest 和 Sinon。可以使用 npm 进行安装:

模拟函数行为

Stub

Sinon 中有一个 stub 方法,可以用来替换一个函数并且完全控制它的行为。假设我们有一个名为 getUsername 的函数,它需要调用一个 API 来获取用户的用户名:

为了避免在测试中真正地调用 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:

为了验证 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 的函数,它会在两秒后显示一个问候信息:

为了在测试中避免等待两秒钟,我们可以使用 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

纠错
反馈