我是 React Hooks 的新手,我想要实现的是测试一个 React 组件(称为 CardFooter(,该组件包含一个对 useEffect 钩子的调用,该钩子被触发全局上下文变量被修改。
卡页脚.js:
const CardFooter = props => {
const [localState, setLocalState] = useState({
attachmentError: false
});
const globalContext = useContext(GlobalContext);
React.useEffect(()=> {
setLocalState({
...localState,
attachmentError: globalContext.data.attachmentError
});
},[globalContext.data.attachmentError]);
}
CardFooter.test.js:
import Enzyme, { shallow } from 'enzyme';
Enzyme.configure({ adapter: new Adapter() });
describe('<CardFooter />', () => {
let useEffect;
const mockUseEffect = () => {
useEffect.mockImplementation(f => f());
};
useEffect = jest.spyOn(React, "useEffect");
mockUseEffect(); //
it('should render correctly with no props.', () => {
}
const mockUseEffect = () => {
useEffect.mockImplementation(f => f());
};
useEffect = jest.spyOn(React, "useEffect");
mockUseEffect();
const wrapper = shallow(<CardFooter />);
expect(toJson(wrapper)).toMatchSnapshot();
});
运行测试时遇到的错误是:
类型错误: 无法读取未定义的属性"附件错误"
我尝试了这里介绍的方法:https://medium.com/@pylnata/testing-react-functional-component-using-hooks-useeffect-usedispatch-and-useselector-in-shallow-9cfbc74f62fb.然而,似乎 Shallow 并没有选择模拟的 useEffect 实现。我还尝试嘲笑useContext和globalContext.data.attachmentError。似乎什么都不起作用。
试试这个。请注意,"jest.spyOn"被放置在"beforeEach"中。
beforeEach(() => {
jest.spyOn(React, "useEffect").mockImplementationOnce(cb => cb()());
// .... other things ....
}
如果你想"触发"模拟的useEffect,你可以这样做:
useEffect.mock.calls[index][0](useEffect.mock.calls[index][1])
index
按运行的顺序选择 useEffect 调用。例如,如果您有此钩子:
const useHook = () => {
useEffect(() => {
functionToMock1()
}, []);
useEffect(() => {
functionToMock2()
}, []);
}
你可以用这个来做第二个useEffect触发器:useEffect.mock.calls[1][0](useEffect.mock.calls[1][1])
,这将允许你断言functionToMock2()
。即:
jest.mock('../functions', () => ({
functionToMock1: jest.fn(),
functionToMock2: jest.fn(),
}))
describe('useHook', () => {
it('runs functionToMock2', () => {
useHook();
// trigger first useEffect
useEffect.mock.calls[0][0](useEffect.mock.calls[0][1]);
assert(functions.functionToMock1).toHaveBeenCalled();
assert(functions.functionToMock2).not.toHaveBeenCalled();
// trigger second useEffect
useEffect.mock.calls[1][0](useEffect.mock.calls[1][1]);
assert(functions.functionToMock2).toHaveBeenCalled();
})
})