【问题标题】:Using Jest and Enzyme to test functional React components that are using Redux使用 Jest 和 Enzyme 测试使用 Redux 的功能性 React 组件
【发布时间】: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 从中分离出来,这样测试就不需要要模拟的商店?

【问题讨论】:

    标签: reactjs redux react-redux jestjs react-hooks


    【解决方案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 试了一下,效果很好!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 2019-07-26
    • 2018-08-20
    • 1970-01-01
    • 2017-04-13
    相关资源
    最近更新 更多