You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jest和Enzyme测试React Redux应用Login组件报错如何解决

错误原因及修复方案

核心错误点

  • 渲染方法使用错误:用shallow渲染包裹了Provider的组件时,shallow只会渲染Provider本身,不会向下渲染内部的Login组件,所以查找的元素全部不存在,自然返回false。
  • 模拟store属性缺失:mapStateToProps里用到了isLoggedIn、role、globalmessage、authToken、loggedUserInfo这些属性,但你初始化mock store的时候只传了email和password,会导致组件渲染异常。
  • 选择器写错:Email对应的Field组件type属性是text不是email(查看Login.js代码可确认<Field as={TextField} label="Email" ... type="text" name="email" />),用Field[type='email']无法匹配到目标元素。
  • 依赖缺失:组件用到了useHistory,测试环境没有路由上下文,需要先mock这个hook避免报错。

修复后的完整测试代码

import { mount } from "enzyme";
import Login from "../Login";
import { Provider } from "react-redux";
import configureStore from "redux-mock-store";

// mock react-router的useHistory
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useHistory: () => ({ push: jest.fn() })
}))
const mockStore = configureStore([]);

describe("Login Component", () => {
  let store;
  let jsx;

  beforeEach(() => {
    // 补全login state所有必填属性
    store = mockStore({ 
      login: { 
        email: "", 
        password: "",
        isLoggedIn: false,
        role: "",
        globalmessage: "",
        authToken: "",
        loggedUserInfo: { isActive: false }
      } 
    });
    jsx = (
      <Provider store={store}>
        <Login />
      </Provider>
    );
  });

  it("should render an email input tag", () => {
    const wrapper = mount(jsx);
    // 用name属性匹配更精准,不会受type属性修改影响
    expect(wrapper.find("Field[name='email']").exists()).toBe(true);
  });

  it("should render a password input tag", () => {
    const wrapper = mount(jsx);
    expect(wrapper.find('Field[name="password"]').exists()).toBe(true);
  });

  it("should render a submit button", () => {
    const wrapper = mount(jsx);
    expect(wrapper.find('Button[type="submit"]').exists()).toBe(true);
  });
});

可选优化:轻量单元测试方案

如果只测试组件本身的渲染逻辑,不需要耦合Redux,可以单独导出未被connect包裹的原始Login组件,不用配置mock store:

  1. 在Login.js末尾新增导出原始组件:
export const RawLogin = Login; // 新增导出
let hof = connect(mapStatetoProps, mapDispatchToProps);
export default hof(Login);
  1. 测试代码可以简化为:
import { shallow } from "enzyme";
import { RawLogin } from "../Login";

jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useHistory: () => ({ push: jest.fn() })
}))

describe("Login Component", () => {
  const mockProps = {
    isLoggedIn: false,
    role: "",
    globalmessage: "",
    authToken: "",
    currentUser: { isActive: false },
    login: jest.fn(),
    flashNotification: jest.fn()
  }
  it("should render an email input tag", () => {
    const wrapper = shallow(<RawLogin {...mockProps} />);
    expect(wrapper.find("Field[name='email']").exists()).toBe(true);
  });
  // 其余用例同理编写即可
});

内容的提问来源于stack exchange,提问作者pooja thakur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 18:36:01