reactjs - 测试对 redux-saga 函数的调用
问题描述
我正在尝试测试使用ant design
and创建的表单redux-form
。我创建了container
和component
.
我用作redux-saga
中间件。
安装后UserFormContainer
,它会调度操作并redux-saga
执行操作并执行必要的api
调用并返回数据。
有填表的initialize
功能。redux-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: "don@mail.com" },
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();
});
用户窗体.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;
解决方案
这里的问题是我正在尝试测试对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: "don@mail.com" },
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: "don@mail.com" },
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);
推荐阅读
- excel - 如果模式与同一行的另一个单元格中的字符串匹配,则从另一个单元格获取值
- aws-lambda - “无效输入”将 SNS 主题添加为 Lambda 目标
- r - 通过 R 中的 LM 模型的变量列表创建循环
- javascript - Redux thunk 影响不同的 reducer
- java - http java调用出错了
- javascript - 在 react-native 中使用 axios 生成访问令牌
- php - 想要同时提取
从以下 XML 响应中使用 PHP - javascript - 如何为简单的 crud 应用程序创建编辑功能?- 使用 VANILLA JAVASCRIPT 进行 CRUD 操作
- refresh - 在 Raspberry Pi 上刷新铬的问题
- postgresql - 使用Kafka的两种方式数据库同步