【问题标题】:Jest + Enzyme: test Redux-formJest + Enzyme:测试 Redux-form
【发布时间】:2018-09-14 20:41:28
【问题描述】:

我的应用程序有很多 redux-form。我正在使用 Jest 和 Enzyme 进行单元测试。但是,我无法测试 redux-form。我的组件是一个登录表单,例如:

import { login } from './actions';
export class LoginForm extends React.Component<any, any> {

  onSubmit(values) {
    this.props.login(values, this.props.redirectUrl);
  }

  render() {
    const { handleSubmit, status, invalid } = this.props;

    return (
      <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
        <TextField label="Email" name="email">
        <TextField type="password" label="Password" name="password" autoComplete/>
        <Button submit disabled={invalid} loading={status.loading}>
          OK
        </Button>
      </form>
    );
  }
}

const mapStateToProps = (state) => ({
  status: state.login.status,
});

const mapDispatchToProps = { login };

const form = reduxForm({ form: 'login' })(LoginForm);

export default connect(mapStateToProps, mapDispatchToProps)(form);

模拟商店,导入连接组件

redux-form 使用存储来维护表单输入。然后我使用redux-mock-store:

import ConnectedLoginForm from './LoginForm';

const configureStore = require('redux-mock-store');
const store = mockStore({});
const spy = jest.fn(); 

const wrapper = shallow(
  <Provider store={store}>
    <ConnectedLoginForm login={spy}/>
  </Provider>);

wrapper.simulate('submit');
expect(spy).toBeCalledWith();

但是这样一来,submit就没有模拟出来,我的测试用例失败了:

预期的模拟函数已被调用:[] 但它没有被调用。

模拟商店,仅导入 React 组件。

我尝试从测试代码创建 redux 表单:

import { Provider } from 'react-redux';
import ConnectedLoginForm, { LoginForm } from './LoginForm';

const props = {
  status: new Status(),
  login: spy,
};
const ConnectedForm = reduxForm({
  form: 'login',
  initialValues: {
    email: 'test@test.com',
    password: '000000',
  },
})(LoginForm);

const wrapper = shallow(
  <Provider store={store}>
    <ConnectedForm {...props}/>
  </Provider>);

console.log(wrapper.html());

wrapper.simulate('submit');
expect(spy).toBeCalledWith({
  email: 'test@test.com',
  password: '000000',
});

在这种情况下,我仍然收到function not called 的错误。如果我添加console.log(wrapper.html()),则会出现错误:

不变违规:在上下文中找不到“商店”或 “Connect(ConnectedField)”的道具。要么将根组件包装在 a ,或明确地将“store”作为道具传递给 “连接(ConnectedField)”。

我在 redux-form 或 redux 或 jest/enzyme 甚至 Google 的官方网站上找不到文档。请帮忙,谢谢。

【问题讨论】:

    标签: react-redux jestjs jsx redux-form enzyme


    【解决方案1】:

    我使用了真正的商店(因为redux-mock-store 不支持reducer)和redux-form 的reducer,它对我有用。代码示例:

    
    import { createStore, Store, combineReducers } from 'redux';
    import { Provider } from 'react-redux';
    import { reducer as formReducer } from 'redux-form';
    
    const rootReducer = combineReducers({
      form: formReducer,
    });
    
    let store;
    
    describe('Redux Form', () => {
    
      beforeEach(() => {
        store = createStore(rootReducer);
      });
    
      it('should submit form with form data', () => {
        const initialValues = {...};
        const onSubmit = jest.fn();
        const wrapper = mount(
          <Provider store={store}>
            <SomeForm
              onSubmit={onSubmit}
              initialValues={initialValues}
            />
          </Provider>
        );
    
        const form = wrapper.find(`form`);
        form.simulate('submit');
    
        const expectedFormValue = {...};
        expect(onSubmit).toHaveBeenCalledTimes(1);
        expect(onSubmit.mock.calls[0][0]).toEqual(expectedFormValue);
      });
    
    });
    
    

    【讨论】:

      【解决方案2】:

      我制作了一个可以帮助解决此类问题的工具。它使用真实数据(chrome 扩展收集并保存到文件)创建测试用例,您可以通过 CLI 工具运行这些测试用例。 推荐你试试:https://github.com/wasteCleaner/check-state-management

      【讨论】:

        【解决方案3】:

        您可以在这里找到答案:https://github.com/tylercollier/redux-form-test

        简而言之,您可以使用 shallow dive() 函数来测试高阶组件,但在您的情况下,您在高阶组件中有一个高阶组件。

        你需要把你的组件分解成两个组件,第一个是展示组件,没有

        const form = reduxForm({ form: 'login' })(LoginForm);
        export default connect(mapStateToProps, mapDispatchToProps)(form); 
        

        然后将第一个组件包装到第二个组件(容器组件)中。

        您可以轻松测试第一个组件(表示组件)

        【讨论】:

          【解决方案4】:

          我遇到了类似的问题。可以在这里找到答案https://github.com/airbnb/enzyme/issues/1002。 长话短说,您应该将 store 作为道具传递到您的表单中,并在包装​​器上使用 .dive() 函数。

          问候

          帕维尔

          【讨论】:

            猜你喜欢
            • 2019-01-27
            • 2020-11-20
            • 2018-08-28
            • 2018-12-16
            • 2020-03-30
            • 1970-01-01
            • 2023-03-06
            • 2019-01-29
            • 1970-01-01
            相关资源
            最近更新 更多