使用 Jest 和 Enzyme 测试使用 Redux 的功能性 React 组件
Posted
技术标签:
【中文标题】使用 Jest 和 Enzyme 测试使用 Redux 的功能性 React 组件【英文标题】:Using Jest and Enzyme to test functional React components that are using Redux 【发布时间】:2020-04-08 07:03:31 【问题描述】:我正在开发一个 React 项目,我正在使用功能组件和 redux。我正在尝试为我的 RegisterForm 组件编写测试,但 Jest 和 Enzyme 需要一个 redux 存储。
我的组件:
import React, useState from 'react';
import axios from 'axios';
import useSelector, useDispatch from 'react-redux';
import registerRequest, registerSuccess, registerFailure from '../redux/user/userActions';
const RegisterForm = () =>
const dispatch = useDispatch();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [submitDisabled, setSubmitDisabled] = useState(false);
const handleFormSubmit = e =>
e.preventDefault();
setSubmitDisabled(true);
const data = email, password ;
dispatch(registerRequest());
axios.post(`$process.env.REACT_APP_USERS_SERVICE_URL/auth/register`, data)
.then(res =>
dispatch(registerSuccess(res.data.auth_token));
)
.catch(err =>
if (err.response)
dispatch(registerFailure(err.response));
else
dispatch(registerFailure(err));
);
setSubmitDisabled(false);
;
return (
<div className='container'>
<h1>Register</h1>
<form onSubmit=handleFormSubmit>
<div className='form-group'>
<label htmlFor='email' className='row'>
<div className='form-label col-form-label col-sm-2'>Email</div>
<div className='col'>
<input
type='email'
className='form-control'
id='email'
sm='10'
required
value=email
onChange=e => setEmail(e.target.value)
/>
</div>
</label>
</div>
<div className='form-group'>
<label htmlFor='password' className='row'>
<div className='form-label col-form-label col-sm-2'>Password</div>
<div className='col'>
<input
type='password'
className='form-control'
id='password'
sm='10'
required
value=password
onChange=e => setPassword(e.target.value)
/>
</div>
</label>
</div>
<button
type='submit'
className='btn btn-primary'
disabled=submitDisabled
>
Submit
</button>
</form>
</div>
);
;
RegisterForm.propTypes = ;
export default RegisterForm;
由于 React Hooks 仍然相对较新,而且人们不再使用 Redux 进行状态管理,我无法找到足够好的问题/博客文章来讨论处理这种情况的可能方法。
很多人建议采用以下方法:
import configureStore from 'redux-mock-store';
import mount from 'enzyme';
import Provider from 'react-redux';
import RegisterForm from './components/RegisterForm'
const mockStore = configureStore([]);
const store = mockStore(
loading: false,
authToken: '',
error: ''
);
const component = mount(
<Provider store=store>
<RegisterForm />
</Provider>
)
我会使用这种方法,但我不喜欢你必须安装组件的事实。我更愿意使用 shallow 但我找不到使用它的实现。
有什么方法可以将 shallow 与我正在使用的堆栈一起使用,或者是否有其他方法可以构建我的组件以将 redux 从中分离出来,这样测试就不需要要模拟的商店?
【问题讨论】:
【参考方案1】:你可以模拟useDispatch
import useDispatch from 'react-redux';
jest.mock(`react-redux`, () => (
useDispatch: jest.fn()
));
....
beforeEach(() =>
useDispatch.mockClear();
);
...
用useSelector
稍微难一点:
import useSelector from 'react-redux';
jest.mock(`react-redux`, () => (
useSelector: jest.fn()
));
function mockUseSelectorWithData(mockedStore)
useSelector.mockImplementation((callback) => callback(mockedStore));
...
it('...', () =>
const someInitialData = ..... ;
mockUseSelectorWithData(mockedStore);
const wrapper = shallow(<YourComp />);
...
mockUseSelectorWithData(storeWithSomethingChanged);
// changing prop or simulating event to re-render component with new data
....
);
还要注意shallow()
不能正确调用useEffect
hooks。
【讨论】:
刚刚用 useDispatch 试了一下,效果很好!非常感谢!以上是关于使用 Jest 和 Enzyme 测试使用 Redux 的功能性 React 组件的主要内容,如果未能解决你的问题,请参考以下文章
异步 componentDidMount 时使用 React 的 Jest 和 Enzyme 进行测试
如何使用 Jest 和 Enzyme 测试样式组件以具有属性