测试对redux-saga函数的调用

问题描述 投票:0回答:1

我正在尝试测试使用ant designredux-form创建的表单。我已经创建了containercomponent

我已经使用redux-saga作为中间件。

[安装UserFormContainer后,它会分派动作,redux-saga会执行该动作,进行必要的api调用并返回数据。

initializeredux-form功能可以填写表格。

问题是我想测试是否正在填写表格。但是我在调​​用componentdidmount()时无法模拟数据提取。

UserFormContainer.js

import React, { Component } from "react";
import { connect } from "react-redux";
import UserForm from "../component/UserForm";
import { reduxForm } from "redux-form";
import actions from "../redux/actions";

class UserFormContainer extends Component {
  state = {
    loading: false
  };

  componentDidMount() {
    this.setState({
      loading: true
    });
    this.fetchUser();
  }

  fetchUser = () => {
    const { dispatch, initialize } = this.props;

    new Promise((resolve, reject) => {
      dispatch({
        type: actions.FETCH_USER,
        resolve,
        reject
      });
    })
      .then(response => {
        const {
          person: PersonEntityForm,
          contact: EmailEntityForm,
          phone: PhoneEntityForm,
          address: AddressEntityForm
        } = response;

        const userData = {
          PersonEntityForm,
          EmailEntityForm,
          PhoneEntityForm,
          AddressEntityForm
        };

        initialize(userData);
        this.setState({ loading: false });
      })
      .catch(error => console.log({ error }));
  };

  render() {
    const { loading } = this.state;
    return <UserForm loading={loading} />;
  }
}

const UserFormRedux = reduxForm({
  form: "UserForm"
})(UserFormContainer);

export default connect(null, dispatch => ({ dispatch }))(UserFormRedux);

UserFormContainer.test.js

import React from "react";
import { render, cleanup } from "@testing-library/react";
import "@testing-library/jest-dom";
import { reducer as formReducer } from "redux-form";
import { createStore, combineReducers } from "redux";
import { Provider } from "react-redux";
import UserFormContainer from "./UserFormContainer";
import userReducer from "../redux/reducers";
import { FETCH_USER } from "../redux/saga";

afterEach(cleanup);

const renderWithRedux = (
  component,
  {
    initialState,
    store = createStore(
      combineReducers({ userReducer, form: formReducer }),
      initialState
    )
  } = {}
) => {
  return {
    ...render(<Provider store={store}>{component}</Provider>)
  };
};

it("should fill form value", async () => {
  const fakeUser = {
    person: { firstName: "Don", lastName: "Joe" },
    contact: { email: "[email protected]" },
    phone: { phone: "123456789", contactPhoneType: "personal" },
    address: {
      street: "Haven Street",
      street2: null,
      city: "Wingtown",
      state: "Wood",
      postalCode: "44600"
    }
  };

  jest.mock("../redux/saga", () => ({ FETCH_USER: jest.fn() }));
  FETCH_USER.mockImplementation(() => Promise.resolve(fakeUser));

  renderWithRedux(<UserFormContainer />);

  expect(mock).toHaveBeenCalled();
});

UserForm.js

import React, { Component } from "react";
import { FormSection } from "redux-form";
import { Form, Spin } from "antd";
import PersonalInformationForm from "./PersonalInformationForm";
import ContactEmailForm from "./ContactEmailForm";
import ContactPhoneForm from "./ContactPhoneForm";
import ContactAddressForm from "./ContactAddressForm";

class UserForm extends Component {
  render() {
    const { loading } = this.props;

    return (
      <Spin data-testid="spinning" spinning={loading}>
        <Form data-testid="userForm" style={{ width: "300px", margin: "auto" }}>
          <FormSection name="PersonEntityForm">
            <PersonalInformationForm />
          </FormSection>

          <FormSection name="EmailEntityForm">
            <ContactEmailForm />
          </FormSection>

          <FormSection name="PhoneEntityForm">
            <ContactPhoneForm />
          </FormSection>

          <FormSection name="AddressEntityForm">
            <ContactAddressForm />
          </FormSection>
        </Form>
      </Spin>
    );
  }
}

export default UserForm;
reactjs jestjs redux-form redux-saga react-testing-library
1个回答
0
投票

这里的问题是我正在尝试测试对FETCH_USER的函数调用。我的组件使用store.dispatch来调用函数FETCH_USER。因此,我没有测试为FETCH_USER测试的对store.dispatch的函数调用。

UserFormContainer.test.js

import React from "react";
import { render, cleanup } from "@testing-library/react";
import "@testing-library/jest-dom";
import { reducer as formReducer } from "redux-form";
import { createStore, combineReducers } from "redux";
import { Provider } from "react-redux";
import UserFormContainer from "./UserFormContainer";
import userReducer from "../redux/reducers";
import actions from "../redux/actions";

afterEach(cleanup);

const initialState = {};

const fakeStore = createStore(
  combineReducers({ userReducer, form: formReducer }),
  initialState
);

const renderWithRedux = (
  component,
  { initialState, store = fakeStore } = {}
) => {
  return {
    ...render(<Provider store={store}>{component}</Provider>)
  };
};

it("should fill form value", async () => {
  const fakeUser = {
    person: { firstName: "Don", lastName: "Joe" },
    contact: { email: "[email protected]" },
    phone: { phone: "123456789", contactPhoneType: "personal" },
    address: {
      street: "Haven Street",
      street2: null,
      city: "Wingtown",
      state: "Wood",
      postalCode: "44600"
    }
  };

  fakeStore.dispatch = jest.fn();

 renderWithRedux(<UserFormContainer />);

  expect(fakeStore.dispatch).toHaveBeenCalled();
  expect(fakeStore.dispatch).toHaveBeenLastCalledWith({
    type: actions.FETCH_USER,
    resolve: expect.any(Function),
    reject: expect.any(Function)
  });
});

此外,因为我的dispatch功能包含在new Promise()中。我测试了resolved值,上面的代码略有更改。

const fakeUser = {
  person: { firstName: "Don", lastName: "Joe" },
  contact: { email: "[email protected]" },
  phone: { phone: "123456789", contactPhoneType: "personal" },
  address: {
    street: "Haven Street",
    street2: null,
    city: "Wingtown",
    state: "Wood",
    postalCode: "44600"
  }
};

const fakePromise = new Promise((resolve, reject) => {
    fakeStore.dispatch = jest.fn(() => {
      try {
        resolve(fakeUser);
      } catch (error) {
        reject("error");
      }
    });
  });

  renderWithRedux(<UserFormContainer />);

  expect(fakeStore.dispatch).toHaveBeenCalled();
  expect(fakeStore.dispatch).toHaveBeenLastCalledWith({
    type: actions.FETCH_USER,
    resolve: expect.any(Function),
    reject: expect.any(Function)
  });

  expect(fakePromise).resolves.toBe(fakeUser);
© www.soinside.com 2019 - 2024. All rights reserved.