如何在启用异步验证的情况下测试 redux 表单

How to test a redux form with async validation enabled

我为我的 redux 表单中的一个字段启用了异步验证。我使用 jest 和 enzyme 来测试表单提交。

我尝试用一​​个简单的 resolved promise 模拟异步验证函数,表单仍然无法提交。但是我去掉了异步验证,表单可以毫无问题地提交。

...
jest.mock('../../../../../../utilities/validators');

it('should set registration info and set current step with correct values when registration form is successfully submitted', () => {
    const store = createStore(
      combineReducers({
        form: formReducer,
      }),
    );

    validateEmailUnique.mockImplementation(() => Promise.resolve());

    const mockOnSetRegistrationInfo = jest.fn();
    const mockOnSetRegistrationCurrentStep = jest.fn();

    const updatedProps = {
      ...defaultProps,
      onSetRegistrationInfo: mockOnSetRegistrationInfo,
      onSetRegistrationCurrentStep: mockOnSetRegistrationCurrentStep,
    };

    const wrapper = mount(
      <Provider store={store}>
        <StepOne {...updatedProps} />
      </Provider>,
    );

    const form = wrapper.find('form');
    const businessEmailTextField = wrapper.find(
      'input#business-email-text-field',
    );

    businessEmailTextField.simulate('change', {
      target: {
        value: 'business@email.com',
      },
    });

    form.simulate('submit');

    expect(mockOnSetRegistrationInfo).toHaveBeenCalled();

我希望提交表单,然后调用表单提交回调函数中的 'onSetRegistrationInfo' 函数。但是由于没有通过异步验证,所以测试时无法提交表单。

问题是 expect 运行失败时异步验证尚未完成。

根据我对您代码的了解,您似乎无法从异步验证步骤直接访问 Promise,因此您将无法直接 await ...

...但是如果您模拟了任何 async 操作以立即解决,那么它们应该全部在 Promise 微任务队列的一个周期内完成。

如果是这种情况,那么您可以将您的断言移至 setImmediatesetTimeout 并使用 doneJest 知道测试何时完成:

it('should set registration info...', done => {  // <= use done

  // ...

  form.simulate('submit');

  setImmediate(() => {
    expect(mockOnSetRegistrationInfo).toHaveBeenCalled();  // Success!
    done();  // <= now call done
  });
});