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
的函数:
-- -------------------- ---- ------- ------ ------ - --------- - ---- -------- ------ ---------------- ---- --------------------- ----- ----------------- ------- --------- - -------- - ------ ----------------- --- - - ------ ------- ------------------
我们想要在测试中模拟 MyChildComponent
的 handleClick
函数。以下是我们可以编写的测试代码:
-- -------------------- ---- ------- ------ ----- ---- -------- ------ - ------- - ---- --------- ------ ----------------- ---- ---------------------- ----------------------------- -- -- - ---------- ---- ----------- -- ----- ------ ------- -- -- - ----- ------- - -------------------------- ---- ----- --------------- - ---------- -- -------- ------------------------------------------------------------ - ---------------- -- -- ---- ----- ---------------- ----- ----------- --------- ----------------------------------------- -- - ---------------- --------- ------------------------------------------------- -- ------------ --- ---
在这里,我们使用 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
模拟函数修改如下:
const onSubmitMock = jest.fn().mockReturnValue(true); // 模拟函数总是返回 true
现在,我们修改 expect(onSubmitMock).toHaveBeenCalledWith(email, password)
断言,使其根据 onSubmit
函数的返回值进行断言:
expect(onSubmitMock).toHaveBeenLastCalledWith(email, password); // 断言模拟函数被传入了正确的参数 expect(wrapper.find('form').props().onSubmit()).toBe(true); // 断言表单的 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