无法在 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 设置一个模拟值。