如何用 jasmine 和 enzyme 测试 React useEffect hooks
How to test React useEffect hooks with jasmine and enzyme
我找不到如何在测试我的组件时调用我的 useEffect 挂钩。
我尝试了几种类似的解决方案,但都没有用:https://reactjs.org/docs/test-utils.html#act
我的组件:
const mapDispatchToProps = (dispatch: IDispatch, ownProps: ITextAreaOwnProps): ITextAreaDispatchProps => ({
onMount: () => dispatch(addTextArea(ownProps.id)),
});
export const TextArea = (props) => {
React.useEffect(() => {
props.onMount();
}, []);
// more code... //
return (
<>
<TextareaTagName
{...props.additionalAttributes}
className={props.className}
/>
{props.children}
{getValidationLabel()}
</>
);
};
我的测试:
it('should call prop onMount on mount', () => {
const onMount = jasmine.createSpy('onMount');
mount(<TextArea id="textarea-id" onMount={onMount} />);
expect(onMount).toHaveBeenCalledTimes(1);
});
简短的回答是您不能直接测试它。您基本上需要触发组件中的更改检测以激活 useEffect
挂钩。您可以通过这样的方式轻松使用 react-dom/test-utils
库
import { act } from 'react-dom/test-utils';
import { shallow, mount } from 'enzyme';
it('should call prop onMount on mount', () => {
const onMount = jasmine.createSpy('onMount');
const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);
act(() => {
wrapper.update();
});
expect(onMount).toHaveBeenCalledTimes(1);
});
关于文档,useEffect 应该在任何道具更改时更新。
- 您可以使用其他道具回忆测试。
- 可以模拟一下使用效果。
/* mocking useEffect */
useEffect = jest.spyOn(React, "useEffect");
mockUseEffect(); // 2 times
mockUseEffect(); //
const mockUseEffect = () => {
useEffect.mockImplementationOnce(f => f());
};
测试 onMount 函数调用的方法是调用 wrapper.update()
方法。您必须使用来自酶的 mount
,因为 shallow
尚不支持调用挂钩。更多关于这里的问题 -
useEffect not called when the component is shallow rendered #2086
import { mount } from 'enzyme';
it('should call prop onMount on mount', () => {
// arrange
const onMount = jasmine.createSpy('onMount');
const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);
// act
wrapper.update();
// assert
expect(onMount).toHaveBeenCalledTimes(1);
});
如果您在 useEffect 挂钩中进行 api 调用,则必须更新 setTimeout 挂钩中的包装器,以便将更改反映在组件上。
import { mount } from 'enzyme';
it('should call prop onMount on mount', () => {
// arrange
const onMount = jasmine.createSpy('onMount');
const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);
setTimeout(() => {
// act
wrapper.update();
// assert
expect(onMount).toHaveBeenCalledTimes(1);
});
});
我找不到如何在测试我的组件时调用我的 useEffect 挂钩。
我尝试了几种类似的解决方案,但都没有用:https://reactjs.org/docs/test-utils.html#act
我的组件:
const mapDispatchToProps = (dispatch: IDispatch, ownProps: ITextAreaOwnProps): ITextAreaDispatchProps => ({
onMount: () => dispatch(addTextArea(ownProps.id)),
});
export const TextArea = (props) => {
React.useEffect(() => {
props.onMount();
}, []);
// more code... //
return (
<>
<TextareaTagName
{...props.additionalAttributes}
className={props.className}
/>
{props.children}
{getValidationLabel()}
</>
);
};
我的测试:
it('should call prop onMount on mount', () => {
const onMount = jasmine.createSpy('onMount');
mount(<TextArea id="textarea-id" onMount={onMount} />);
expect(onMount).toHaveBeenCalledTimes(1);
});
简短的回答是您不能直接测试它。您基本上需要触发组件中的更改检测以激活 useEffect
挂钩。您可以通过这样的方式轻松使用 react-dom/test-utils
库
import { act } from 'react-dom/test-utils';
import { shallow, mount } from 'enzyme';
it('should call prop onMount on mount', () => {
const onMount = jasmine.createSpy('onMount');
const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);
act(() => {
wrapper.update();
});
expect(onMount).toHaveBeenCalledTimes(1);
});
关于文档,useEffect 应该在任何道具更改时更新。
- 您可以使用其他道具回忆测试。
- 可以模拟一下使用效果。
/* mocking useEffect */
useEffect = jest.spyOn(React, "useEffect");
mockUseEffect(); // 2 times
mockUseEffect(); //
const mockUseEffect = () => {
useEffect.mockImplementationOnce(f => f());
};
测试 onMount 函数调用的方法是调用 wrapper.update()
方法。您必须使用来自酶的 mount
,因为 shallow
尚不支持调用挂钩。更多关于这里的问题 -
useEffect not called when the component is shallow rendered #2086
import { mount } from 'enzyme';
it('should call prop onMount on mount', () => {
// arrange
const onMount = jasmine.createSpy('onMount');
const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);
// act
wrapper.update();
// assert
expect(onMount).toHaveBeenCalledTimes(1);
});
如果您在 useEffect 挂钩中进行 api 调用,则必须更新 setTimeout 挂钩中的包装器,以便将更改反映在组件上。
import { mount } from 'enzyme';
it('should call prop onMount on mount', () => {
// arrange
const onMount = jasmine.createSpy('onMount');
const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);
setTimeout(() => {
// act
wrapper.update();
// assert
expect(onMount).toHaveBeenCalledTimes(1);
});
});