如何在要测试的React组件中模拟自定义钩子?

ssc*_*ler 8 unit-testing reactjs react-hooks

如果您有一个React组件调用一个获取数据的自定义钩子,那么在测试React组件时模拟内部自定义钩子结果的最佳方法是什么?我看到2种主要方法:

1)Jest.mock自定义钩子。这似乎是最推荐的方法,但是似乎它要求测试对内部实现细节以及可能需要模拟的内容比组件的props接口建议的内容有更多的了解(假设使用prop-type或打字稿)

2)使用依赖项注入方法。将钩子声明为道具,但是将其默认设置为真实的钩子,这样就不必在渲染组件的任何地方都设置钩子,而是允许使用模拟覆盖进行测试。这是一个人为的codeandbox示例,其中包含一个模拟自定义钩子的测试:

https://codesandbox.io/s/dependency-inject-custom-hook-for-testing-mjqlf?fontsize=14&module=%2Fsrc%2FApp.js

2需要更多的输入,但似乎更易于测试。但是,测试已经必须具有组件的内部实现细节的知识,才能测试呈现输出的任何条件逻辑,所以也许这并不重要,而1是最佳方法。是要走的路吗?您看到什么权衡?我是否完全错过了另一种方法?

Kri*_*iti 7

使用 jest 模拟您的自定义钩子。

import * as useCustomHook from '../hooks/useCustomHooks'

const spy = jest.spyOn(useCustomHook, 'default')
spy.mockReturnValue({
name: 'test'
})
Run Code Online (Sandbox Code Playgroud)


hel*_*joe 1

这个问题已经有几个月了,但是如果您还没有找到好的解决方案,我写了一个可能有帮助的包。我经历了类似的思考过程,包括“如果我将钩子注入到组件中会怎样?” 事情变得很奇怪。

我基本上想要一个连接器来避免为演示组件使用额外的包装器来测试它们。

我想出了react-hooks-compose,它可以让你将钩子和演示者分开,并单独或一起测试它们:https ://www.npmjs.com/package/react-hooks-compose

export const useFetch = () => {
  const [user, setUser] = useState();

  useEffect(() => {
    fetchData('some-url') // <-- Fetches data on mount
      .then(res => setUser(res.data));
  }, []);

  return {user};
}

// composeHooks passes the values from your hooks as props
export const UserPresenter = ({user}) => {
  return <div>You fetched data for: {user.name}</div>;
}

export default composeHooks({ useFetch })(DataPresenter);
Run Code Online (Sandbox Code Playgroud)

现在你不必模拟钩子,你可以用 prop 测试演示者:

it('presents user', () => {
  const { queryByText } = render(<UserPresenter user={{name: 'Mary'}} />); // <-- Named export
  expect(queryByText('Mary')).toBeTruthy();
});
Run Code Online (Sandbox Code Playgroud)

或者,您可以选择更高级别的集成测试:

it('fetches data', () => {
  fetchData.mockResolvedValue('Mary');
  const { queryByText } = render(<UserWithData />); // <-- Default export
  expect(queryByText('Mary')).toBeFalsy();
  return wait(() => {
    expect(queryByText('Mary')).toBeTruthy();
  });
});
Run Code Online (Sandbox Code Playgroud)

如果您愿意,您甚至可以对钩子进行单元测试。