如何在 Enzyme 中模拟函数的输入输出

阅读时长 11 分钟读完

Enzyme 是 React 的 UI 测试工具,它可以轻松模拟组件的行为和状态,以便在测试中进行断言和验证。但是,有时候需要模拟组件内部的函数输入输出,这时候就需要用到 Enzyme 提供的模拟函数功能。本文将详细介绍如何在 Enzyme 中模拟函数的输入输出。

1. 模拟组件中的函数

在 Enzyme 中模拟组件中的函数,可以使用 jest.fn() 创建一个模拟函数。模拟函数是一种特殊的函数,它可以记录函数被调用的次数、传入的参数以及返回值。例如,我们有一个组件 MyComponent,其中包含一个名为 handleClick 的函数:

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

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

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

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

现在我们想要在测试中模拟 handleClick 函数,以便在测试中断言它被调用了几次。以下是我们可以编写的测试代码:

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

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

在这里,我们首先创建了一个模拟函数 handleClickMock,然后将其赋值给组件实例的 handleClick 函数。接下来,用 wrapper.find('button').simulate('click') 模拟用户点击按钮,触发 handleClick 函数,然后用 expect(handleClickMock).toHaveBeenCalledTimes(1) 断言模拟函数被调用了一次。

2. 模拟子组件中的函数

在测试组件时,有时候需要模拟子组件中的函数。对于这种情况,我们需要使用 Enzyme 的 dive 方法。dive 方法是一个用于“潜入”到组件中的子组件的方法,使我们能够在测试中直接访问子组件的函数和状态。

考虑一个包含子组件 MyChildComponent 的父组件 MyParentComponent,其中 MyChildComponent 包含一个名为 handleClick 的函数:

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

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

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

我们想要在测试中模拟 MyChildComponenthandleClick 函数。以下是我们可以编写的测试代码:

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

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

在这里,我们使用 wrapper.find(MyChildComponent).dive().instance() 语句来“潜入”到 MyChildComponent 中,并将其实例的 handleClick 函数替换为 handleClickMock 模拟函数。接下来,使用 wrapper.find('button').simulate('click')MyChildComponent 中模拟用户点击按钮,触发 handleClick 函数。最后,使用 expect(handleClickMock).toHaveBeenCalledTimes(1) 断言模拟函数被调用了一次。

3. 模拟函数的返回值

除了记录函数被调用的次数和传入的参数外,模拟函数还可以模拟函数的返回值。这使得我们可以在测试中轻松验证函数的行为,并确保组件和应用程序的行为符合预期。

考虑以下组件和测试代码,其中包含一个带有两个输入框和一个提交按钮的登录表单组件:

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

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

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

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

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

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

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

在这里,我们首先创建了一个模拟函数 onSubmitMock。然后,我们模拟用户输入电子邮件和密码,最后模拟用户提交表单并使用 expect(onSubmitMock).toHaveBeenCalledWith(email, password) 断言模拟函数被传入了正确的参数。但是,这里没有考虑 onSubmit 函数的返回值。

为了模拟 onSubmit 函数的返回值,我们可以使用 jest.fn().mockReturnValue(value) 方法,其中 value 是我们想要模拟的返回值。例如,在上面的测试代码中,我们可以将 onSubmitMock 模拟函数修改如下:

现在,我们修改 expect(onSubmitMock).toHaveBeenCalledWith(email, password) 断言,使其根据 onSubmit 函数的返回值进行断言:

在这里,我们首先使用 expect(onSubmitMock).toHaveBeenLastCalledWith(email, password) 断言模拟函数被传入了正确的参数。接下来,使用 expect(wrapper.find('form').props().onSubmit()).toBe(true) 断言表单的 onSubmit 事件返回真值。

结论

在本文中,我们学习了如何使用 Enzyme 模拟函数的输入输出。我们看到,使用 jest.fn() 方法可以轻松创建模拟函数,使用 dive 方法可以潜入到组件中的子组件中,并使用 expect().toHaveBeenCalledWith() 断言模拟函数被传入正确的参数。我们还看到了如何模拟函数的返回值,并使用返回值来断言表单的行为和状态。这些技术对于编写可靠的和可维护的 UI 测试非常重要,希望能对你有所帮助。

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

纠错
反馈