我正在做一个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从中分离出来,从而使测试不需要商店要嘲笑吗?
答案 0 :(得分:0)
您可以嘲笑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。