当在同一个测试文件中针对不同的测试用例需要mock自定义Hook导出不同的数据时,你可以使用Jest的动态mock功能或者利用Jest的beforeEach
、beforeAll
等钩子函数来设置不同的mock行为。
这里是一个使用Jest的beforeEach
钩子函数来为每个测试用例设置不同mock数据的示例:
// 假设你的自定义Hook位于 ./hooks/useCustomHook.js
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';// 使用jest.mock来模拟整个模块
jest.mock('./hooks/useCustomHook');// 引入模拟的Hook,注意这里使用require而不是import,因为我们需要能够修改它
const useCustomHookMock = require('./hooks/useCustomHook').useCustomHook;
* 我这边是默认导出值,所以用的require('./hooks/useCustomHook').default
describe('MyComponent', () => {beforeEach(() => {// 可以在这里重置mock,确保每个测试用例的mock都是独立的useCustomHookMock.mockReset();});it('renders data for test case 1', () => {// 设置mock的返回值useCustomHookMock.mockReturnValue({ someData: 'mocked data for test case 1' });const wrapper = shallow(<MyComponent />);expect(wrapper.text()).toBe('mocked data for test case 1');});it('renders data for test case 2', () => {// 设置另一个mock的返回值useCustomHookMock.mockReturnValue({ someData: 'mocked data for test case 2' });const wrapper = shallow(<MyComponent />);expect(wrapper.text()).toBe('mocked data for test case 2');});// 你可以继续添加更多的测试用例,并为它们设置不同的mock返回值
});
注意几个关键点:
-
使用
jest.mock
:在测试文件的顶部使用jest.mock
来模拟整个模块。这将确保在测试运行时,所有对./hooks/useCustomHook
的引用都将被mock版本替代。 -
动态设置mock返回值:在每个测试用例中,使用
mockReturnValue
来动态设置mock的返回值。这样,每个测试用例都可以有它自己的mock数据。 -
重置mock:在
beforeEach
钩子函数中调用mockReset
来重置mock,确保每个测试用例的mock行为是独立的,不会受到前一个测试用例的影响。 -
使用
require
而不是import
:当需要动态修改mock行为时,最好使用require
而不是import
来引入mock的Hook。这是因为import
是静态的,在模块加载时就已经确定了,而require
允许你在运行时动态地更改模块的内容。
但是,请注意,如果你使用的是ES Modules(即使用import
/export
而不是require
/module.exports
),你可能需要使用一些额外的配置或技巧来动态地修改mock的行为。不过,在大多数情况下,上述方法应该足够用。
另外,如果你正在使用React 18和Concurrent Mode,或者想要更纯粹的组件测试方法,你可能会考虑使用React Testing Library(RTL)而不是Enzyme。RTL与Jest结合使用时,虽然不直接支持Hook的mock,但它提供了更贴近用户实际使用场景的组件测试方式。对于Hook的mock,你仍然可以通过上述方法来实现。