Jest 测试中遇到的 Mock 问题及解决方法

阅读时长 8 分钟读完

前言

在前端开发中,测试已经成为了一个非常重要的环节。作为前端测试框架的代表之一,Jest 是一款十分流行的测试工具。在 Jest 中,Mock 是非常重要的一个概念,它可以帮助我们模拟一些外部依赖,使得我们在测试中能够更容易地进行单元测试。但是,Mock 也会引出一些问题,本文将会介绍 Jest 测试中遇到的 Mock 问题以及解决方法。

背景

在 Jest 中,我们使用 Mock 可以通过模仿一些函数和方法的行为来达到依赖注入和控制反转的目的,以方便我们进行单元测试。在实际开发中,经常会有这样的情况:如果一个组件或函数依赖了其他模块或库,我们就可以用 Mock 来模拟这些依赖。不过,Mock 虽然能够帮助我们更容易地进行测试,但是在实际使用中,也会出现一些问题。

问题

问题一:Mock 无法正确 Mock 模块导出的方法

有时候我们希望 Mock 一个模块中导出的方法,但是在 Jest 中却无法正常 Mock,导致测试无法进行。例如:

-- -------------------- ---- -------
-- ----------
-- ------------------
------ -------- ------ -- -
  ------ - - --
-

-- ------------
-- --------------------
------ - --- - ---- ----------

------ -------- ------ -- -
  ------ ------ ---
-

我们要测试 compute.js 中的 sum 方法,由于它依赖了 index.js 中的 add 方法,我们可以通过引入一个 Mock 来模拟 add 方法。下面是我们的测试代码:

-- -------------------- ---- -------
-- -----------------------------
------ - --- - ---- ---------------------
------ - -- ----- ---- -------------

-- ---- --- --
----------------------------- -- -- --
  ---- ----------
----

--------- ------ -- -------- -- -- -
  ------ ---
  -- -- --- ---------
  -------------------------------------
---

在测试中,我们使用了 jest.mock() 方法来 Mock index.js 中的 add 方法。然而,我们运行测试时却发现,add 方法并没有被成功 Mock。这是因为在 index.js 文件中,add 方法是直接导出的,而不是作为一个对象的属性导出,导致 Jest 无法正确 Mock。

问题二:Mock 会影响测试结果

另外一个问题是,如果 Mock 的不当,有可能会导致测试结果不准确。例如,我们有这样一个组件:

-- -------------------- ---- -------
------ ----- ---- --------
------ --- ---- -----------

-------- --------------- -
  ----- ---------- ------------ - ---------------

  ------------ -- -
    ----- -------- ----------- -
      ----- -------- - ----- ------------------------------
      ----------------------
    -

    ------------
  -- ----------------

  -- ----------- -
    ------ ---------------------
  -

  ------ -
    -----
      -------- -------------------
      ------- ------------------
    ------
  --
--

在该组件中,我们通过 api 对象来获取用户信息。在测试中,我们可以使用 Mock 来模拟 api 对象,从而测试组件的状态和渲染是否正确:

-- -------------------- ---- -------
------ ----- ---- --------
------ --- ---- -----------
------ - ------- ------- ------- - ---- -------------------------
------ -------- ---- ----------------

--------------------- -- -- --
  ------------ ----------
----

-------------- ------ ------ ----------- ----- -- -- -
  ----------------------------------- ----- ------- ---- -- ---
  ---------------- ---------- ----
  ----- ---------- -- -
    ------------------------------------------------------
    ----------------------------------------------------
  ---
---

然而,如果我们 Mock 的不当,有可能会引起测试结果不准确。举个例子,如果我们将 getUserInfo 方法 Mock 为:

此时 getUserInfo 方法将会直接返回一个对象,而不是 Promise,这样就会导致在测试中无法正确地模拟异步操作,从而导致测试结果不准确。

解决方法

那么,我们要怎么解决上述的问题呢?接下来,将会从两个方面介绍解决方法。

解决 Mock 无法正确 Mock 模块导出的方法

针对第一个问题,我们可以将需要 Mock 的方法设置在一个对象上,然后再将该对象导出。这样,Mock 的时候就可以 Mock 对象的属性,而不是直接 Mock 方法,这样就能够正确 Mock 模块导出的方法了。改写前面的代码如下:

-- -------------------- ---- -------
-- ------------------
------ ----- ----- - -
  ------ -- -
    ------ - - --
  -
-

-- --------------------
------ - ----- - ---- ----------

------ -------- ------ -- -
  ------ ------------ ---
-

测试代码:

-- -------------------- ---- -------
-- -----------------------------
------ - --- - ---- ---------------------
------ - ----- - ---- -------------------

-- ---- --- --
----------------------------- -- -- --
  ------ -
    ---- ----------
  -
----

--------- ------ -- -------- -- -- -
  ------ ---
  -- -- --- ---------
  -------------------------------------
---

在上述代码中,我们将需要 Mock 的方法 add 放在了 utils 对象上,然后再将 utils 暴露出去。在测试代码中,我们通过 Mock utils 对象的属性,从而可以 Mock add 方法。

解决 Mock 会影响测试结果

针对第二个问题,我们可以通过 Jest 提供的一些 Mock 方法来 Mock 函数的行为,从而尽量不影响测试结果。例如,我们可以使用 jest.fn() 来创建一个 Mock 函数,然后根据情况设置返回值。举个例子,我们可以将前面的 Mock 修改为:

-- -------------------- ---- -------
--------------------- -- -- --
  ------------ ----------
----

-------------- ------ ------ ----------- ----- -- -- -
  ----------------------------------- ----- ------- ---- -- ---
  ---------------- ---------- ----
  ----- ---------- -- -
    ------------------------------------------------------
    ----------------------------------------------------
  ---
---

在这个例子中,我们使用 jest.fn() 创建了一个 Mock 函数,然后使用 mockResolvedValue 方法设置了该函数的返回值。在这种情况下,我们能够保留动态解析的异步操作,从而得到准确的测试结果。

总结

Mock 是 Jest 中一个非常重要的概念,它能够帮助我们模拟一些外部依赖,从而方便我们在测试过程中进行单元测试。但是,Mock 也会带来一些问题,例如无法正确 Mock 模块导出的方法以及可能会影响测试结果等。要解决这些问题,我们可以将需要 Mock 的方法设置在一个对象上,然后再将该对象导出,以正确 Mock 模块导出的方法;同时,在 Mock 时要尽量避免影响测试结果,可以使用 Jest 提供的一些 Mock 方法来模拟函数的行为,以得到准确的测试结果。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64b2093b48841e9894e5e47a

纠错
反馈