Jest 测试中 mock 函数的使用及其实际用例

阅读时长 10 分钟读完

前言

Jest 是一个广泛使用的 JavaScript 测试框架,其能够快速高效地进行单元测试、集成测试等各类测试。在测试过程中,经常需要模拟函数等操作,这时候 mock 函数就派上用场了。本文将介绍 Jest 中 mock 函数的使用及其实际用例,希望能对前端开发者进行指导和帮助。

mock 函数简介

mock 函数是一种测试用的函数,其可以模拟代码中的函数、对象,以便测试其方法时不需要真正调用该函数或对象。Jest 中的 mock 函数提供了以下三种方式:

  • 普通函数 mock
  • 模块 mock
  • 对象属性 mock

通过 Jest 提供的 mock 函数,我们可以在测试过程中创建虚拟的或是假的函数或对象,从而避免我们真实调用代码中的函数或对象,这样可以大幅减小测试带来的风险。下面将从以上三种方式依次介绍 Jest 中 mock 函数的使用。

普通函数 mock

在测试过程中,有时候我们需要测试某个函数是否被调用、调用的次数、传入的参数是否正确等。这时候我们可以使用 Jest 提供的 mock 函数来模拟该函数。

语法

以下是 Jest 中 mock 函数的语法:

该函数会返回一个 mock 函数,我们可以使用该函数来模拟真正的函数。例如:

上述例子中,我们首先定义了一个实际的函数 add,然后使用 jest.fn() 创建一个 mock 函数 mockFn,最后调用 mockFn。

返回值

使用 Jest 提供的 mock 函数,可以通过多种方式确定函数调用时的返回值。以下是三种方式:

  • mockReturnValue(value): 当函数被调用时,会始终返回 value。
  • mockResolvedValue(value): 用于异步函数的 mock。当异步函数被调用时,resolve 会始终返回 value。
  • mockRejectedValue(value): 用于异步函数的 mock。当异步函数被调用时,reject 会始终返回 value。

函数属性

Jest 中 mock 函数还支持以下一些属性:

  • jest.fn().mock.calls.length:记录函数被调用的次数
  • jest.fn().mock.calls[index][argIndex]:记录函数被调用的参数
  • jest.fn().mock.results[index].value:记录函数返回值(只有在使用 mockReturnValue 指定返回值后才有)

以 mock.calls 属性为例:

上述例子中,我们首先定义了一个 mock 函数 mockFn,然后调用 mockFn,并记录函数被调用的次数、传入的参数。

模块 mock

在引入某个模块时,如果该模块中存在一些不稳定、不好测试的函数等,我们可以使用 Jest 提供的模块 mock 来模拟模块中的函数。

语法

以下是 Jest 中模块 mock 的语法:

  • moduleName:要 mock 的模块名称
  • factory:指定 mock 规则的函数
  • options:可选项,用于设置一些限制条件等

例如请见下面的代码片段:

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

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

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

------------------ ---- -- --
展开代码

在上述例子中,我们首先定义了一个 utils.js 文件,其中包含了一个 add 函数。然后,在 test.ts 文件中引入了这个模块,并使用 jest.mock() 针对该模块进行了 mock。转换后的模块返回了一个只含有 add 函数的对象,并且该函数被赋予了一个返回值。最后,我们调用了测试模块中的 add 函数,并输出了其值。

通俗的说,就是通过 jest.mock() 重新实现了一个 utils.js。在写测试用例时,会默认使用 mock 之后的 utils.js,而不是真正的 utils.js。

需要注意的是,模块 mock 是对模块整体进行 mock,而不仅仅是 mock 其中的某个函数。所以在使用模块 mock 的时候,需要注意这一点。

对象属性 mock

在开发过程中,往往会使用对象,为了在测试过程中避免使用到真实的对象,我们同样可以使用 Jest 提供的对象属性 mock 来模拟对象中的属性或方法。

语法

以下是 Jest 中对象属性 mock 的语法:

其中,object 表示要进行 mock 的对象,methodName 表示要进行 mock 的函数名。

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

-- ---- --
----- ------- - --- ----------
----- ------ - ------------------- -------
展开代码

在上述例子中,我们首先定义了一个 MyClass 类和其中的 add 函数,然后使用 jest.spyOn() 创建了一个针对 myClass.add 的 mock 函数。

要注意的是,Jest 中对象属性 mock 只能 mock 实例化出的对象,而不能直接 mock 对象本身。

mock 返回值

对象属性 mock 与普通函数 mock 相同,具有相同的 mockReturnValue 和 mockResolvedValue、mockRejectedValue 方法。

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

-- ---- --
----- ------- - --- ----------
----- ------ - ------------------- ---------------------------
展开代码

在上述例子中,我们仍然使用了 MyClass 和 add 函数,然后使用 jest.spyOn() 创建了一个针对 add 函数的 mock,该函数在被调用时,始终返回 42。

实际用例

测试 Promise 使用异步 Jest 测试

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

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

------ ------- -----
展开代码
  • login:用户登录操作
  • logout:用户退出登录操作

正常输入

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

---------------- -- -- -
  --------- -------------- ----- -- -- -
    ----- ------ - ----- ------------------- -------
    ----------------------------
  ---
  
  ---------- -------------- ----- -- -- -
    ----- --------------
  ---
--
展开代码

在正常输入的情况下,我们只关心测试是否通过。测试会等待 1s 后,判断结果是否符合。如果符合,表示测试通过。

错误输入

在错误输入的情况下,我们关心测试是否真正抛出了错误,以及错误内容是否合法。

-- -------------------- ---- -------
-- ------------
---------------- -- -- -
  --------- -------- ----- -- -- -
    ----- --- - ------------------- -------
    ----- ------ - ----- ------------------- ----------
    --------------------------------------- ------- ------- -----------
    ---------------------------
  ---
--
展开代码

以上代码的运行过程:

  • 调用 User.login("admin", "123456"),测试用户登录操作
  • 调用 console.log("login failed: Invalid password"),测试 console.log 是否被调用
  • 断言登录结果正确性

至此,我们成功实现了 Promise 异步 Jest 测试,并针对不同输入进行了多重测试,同时使用 Jest.mock() 实现了对 add 的 mock,确保测试结果的准确性及健壮性。

tip

在使用 mock 函数的过程中,我们还可以使用 beforeAll、beforeEach 这类函数,让 mock 的函数可以被重复使用。而该部分也不需要我们进行手动清理的操作,Jest 会自行负责清理。

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

纠错
反馈

纠错反馈