无法在 Jest 和 Enzyme React 17 中读取未定义的属性(读取 'find')
Cannot read properties of undefined (reading 'find') in Jest and Enzyme React 17
我正在使用 v17 开发一个 React 应用程序。我有一个增加费用的组件。组件中的功能在 GUI 中按预期工作,但当我尝试使用 jest/enzyme
对其进行测试时,它会抛出 TypeError: Cannot read properties of undefined (reading 'find')
错误。在 GUI 中,它发现我正在尝试编辑的费用没有问题。我在尝试匹配快照时是否没有正确测试它?
编辑费用构成
import React from "react";
import { useParams } from "react-router-dom";
import { connect } from "react-redux";
import { ExpenseForm } from "./ExpenseForm";
import { editExpense, removeExpense } from "../actions/expenses";
//React router
import { useNavigate } from "react-router-dom";
export const EditExpensePage = (props) => {
const navigate = useNavigate();
const { expenseID } = useParams();
const foundExpense = props.expenses.find(
(expense) => expense.id === expenseID
);
return (
<div>
<h1>Edit Expense</h1>
<ExpenseForm
expense={foundExpense}
onSubmit={(expense) => {
// //Edit expense action expects 2 params (id, updates)
props.editExpense(expenseID, expense);
// //Redirect to dashboard
navigate("/");
}}
/>
<button
onClick={(e) => {
e.preventDefault();
props.removeExpense(expenseID);
navigate("/");
}}
>
Remove Expense
</button>
</div>
);
};
const mapStateToProps = (state, props) => ({
expenses: state.expenses
});
const mapDispatchToProps = (dispatch) => ({
editExpense: (id, expense) => dispatch(editExpense(id, expense)),
removeExpense: (id) => dispatch(removeExpense(id))
});
export default connect(mapStateToProps, mapDispatchToProps)(EditExpensePage);
当前测试
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let history, editExpense, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
更新了测试中的 editExpense 值
const setup = (props) => {
//editExpense = testExpenses[1]; //Same error
editExpense = jest.fn(); //Same error
let removeExpense = jest.fn();
let history = jest.fn();
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
更新测试文件
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let editExpense, expenseID, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
expenseID = 1;
editExpense = [testExpenses.find((expense) => expense.id === expenseID)];
console.log(editExpense);
//Output from this console log
// [
// {
// id: 1,
// description: 'Wifi payment',
// note: 'Paid wifi',
// amount: 10400,
// createdAt: 13046400000
// }
// ]
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
更新了您的代码
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let history, editExpense, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
editExpense = testExpenses; //it should be an array like this [{ id: 1 }]
const component = shallow(
<EditExpensePage
{...props}
expenses={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
您的 EditExpensePage
正在调用 props.expenses
,但在您的测试用例中,您从未设置它。
这里只介绍一下
let history, editExpense, removeExpense, wrapper;
但是您还没有设置 editExpense
的值,这意味着它是未定义的。
这就是 undefined.find
抛出错误的原因。
我建议您为 editExpense
设置一个模拟值。
我正在使用 v17 开发一个 React 应用程序。我有一个增加费用的组件。组件中的功能在 GUI 中按预期工作,但当我尝试使用 jest/enzyme
对其进行测试时,它会抛出 TypeError: Cannot read properties of undefined (reading 'find')
错误。在 GUI 中,它发现我正在尝试编辑的费用没有问题。我在尝试匹配快照时是否没有正确测试它?
编辑费用构成
import React from "react";
import { useParams } from "react-router-dom";
import { connect } from "react-redux";
import { ExpenseForm } from "./ExpenseForm";
import { editExpense, removeExpense } from "../actions/expenses";
//React router
import { useNavigate } from "react-router-dom";
export const EditExpensePage = (props) => {
const navigate = useNavigate();
const { expenseID } = useParams();
const foundExpense = props.expenses.find(
(expense) => expense.id === expenseID
);
return (
<div>
<h1>Edit Expense</h1>
<ExpenseForm
expense={foundExpense}
onSubmit={(expense) => {
// //Edit expense action expects 2 params (id, updates)
props.editExpense(expenseID, expense);
// //Redirect to dashboard
navigate("/");
}}
/>
<button
onClick={(e) => {
e.preventDefault();
props.removeExpense(expenseID);
navigate("/");
}}
>
Remove Expense
</button>
</div>
);
};
const mapStateToProps = (state, props) => ({
expenses: state.expenses
});
const mapDispatchToProps = (dispatch) => ({
editExpense: (id, expense) => dispatch(editExpense(id, expense)),
removeExpense: (id) => dispatch(removeExpense(id))
});
export default connect(mapStateToProps, mapDispatchToProps)(EditExpensePage);
当前测试
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let history, editExpense, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
更新了测试中的 editExpense 值
const setup = (props) => {
//editExpense = testExpenses[1]; //Same error
editExpense = jest.fn(); //Same error
let removeExpense = jest.fn();
let history = jest.fn();
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
更新测试文件
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let editExpense, expenseID, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
expenseID = 1;
editExpense = [testExpenses.find((expense) => expense.id === expenseID)];
console.log(editExpense);
//Output from this console log
// [
// {
// id: 1,
// description: 'Wifi payment',
// note: 'Paid wifi',
// amount: 10400,
// createdAt: 13046400000
// }
// ]
const component = shallow(
<EditExpensePage
{...props}
expense={editExpense}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
更新了您的代码
import React from "react";
import { shallow } from "enzyme";
import { EditExpensePage } from "../../components/EditExpensePage";
import { testExpenses } from "../fixtures/expenses";
let history, editExpense, removeExpense, wrapper;
//Mock for use navigate
const mockedUsedNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUsedNavigate
}));
const setup = (props) => {
editExpense = testExpenses; //it should be an array like this [{ id: 1 }]
const component = shallow(
<EditExpensePage
{...props}
expenses={editExpense}
history={history}
removeExpense={removeExpense}
/>
);
return {
component: component
};
};
describe("EditForm component", () => {
beforeEach(() => {
setup();
});
test("should render EditExpensePage", () => {
expect(wrapper).toMatchSnapshot();
});
});
您的 EditExpensePage
正在调用 props.expenses
,但在您的测试用例中,您从未设置它。
这里只介绍一下
let history, editExpense, removeExpense, wrapper;
但是您还没有设置 editExpense
的值,这意味着它是未定义的。
这就是 undefined.find
抛出错误的原因。
我建议您为 editExpense
设置一个模拟值。