【问题标题】:NodeJs JavaScript heap out of memory crash on react-scripts-ts after adding tests添加测试后,NodeJs JavaScript堆内存崩溃在react-scripts-ts上
【发布时间】:2021-12-20 14:01:12
【问题描述】:

我有一个 react + typescript 项目。从几天前开始,我的 webstorm IDE 崩溃(JavaScript 堆内存不足)on every update that I make to codes。我正在使用 nodeJs 12.3.1、typescript 3.7.5、react 16.12.0、react-scripts-ts 3.1.0、webstorm 2021.2,我的操作系统是 windows 10。

自那时以来,我所做的唯一重大更改是添加了一堆测试(准确地说是 5000 行代码的 48 个测试)。这些测试是使用 jest 和酵素编写的。这些测试包括模拟一些 API 和事件,以及安装元素以检查它们的存在和状态。我应该说所有这些测试都会通过。

我的问题是为什么 nodeJs 在我每次更改代码后都会中断? react-scripts-ts starthot reloads 做了什么?在编写测试时我应该考虑一些特定的隐藏点吗?

如果能找到问题的任何帮助或线索,我将不胜感激。

PS:我很乐意分享任何必要的信息来帮助澄清问题。

这是其中一项测试的代码:

import * as React from 'react';
import * as Adapter from 'enzyme-adapter-react-16';
import * as enzyme from 'enzyme';
import DonutObjectKpi from './donutObjectKpi';
import {
  ChartType,
  DashboardItemType,
  DonutChartProps,
  NamedKpiSeriesSelector,
} from '../../../../utils/dashboardUtils/dashboardItem/props';
import KpiDefinition from '../../../../../model/kpi/customKpi/kpiDefinition';
import Kpi from '../../../../../model/kpi/kpi';
import KpiDefinitionType from '../../../../../model/kpi/kpiDefinitionType';
import { CHART_REFRESH_RATE } from '../../../../../config/constants';
import { Button, HorizontalLayout, IconButton, PieChartType, Table } from '../../../../view';
import { InputLabeledField } from '../../../../../modules/panels/baseCrud/layouts';
import { EnumDropDown } from '../../../../input';
import BuildOption from '../../../dropdown/buildOption/component';

enzyme.configure({adapter: new Adapter()});
describe('ObjectKpiItem Test', () => {
  let chartType = ChartType.DONUT;
  let showTitle = true;
  let title: string | undefined = 'Test';
  let cancelModal: boolean = false;
  let dataModal: DonutChartProps | undefined;
  let changeType: boolean = false;
  const obj = {value: '1', label: 'item1'};
  const resourceObj = {value: '2', label: 'item2'};
  const kpiDef: KpiDefinition = {
    kpi: Kpi.DB2Z_DSCDBAT,
    type: KpiDefinitionType.OBJECT_KPI,
    monitoringObject: {id: '3', presentation: 'item3'},
  };
  const description = 'donut Test';

  const selectors: NamedKpiSeriesSelector[] = [
    {kpi: Kpi.ACTIVE_DIRECTORY_COMPUTERS_COUNT, kpiDefinition: kpiDef, objectId: '1', objectIdName: 'item1'},
    {kpi: Kpi.ACTIVE_DIRECTORY_DISABLED_USERS_COUNT, kpiDefinition: kpiDef, objectId: '2', objectIdName: 'item2'},
    {kpi: Kpi.HBASE_REGION_SERVER_STORE_FILE_SIZE_20210, kpiDefinition: kpiDef, objectId: '3', objectIdName: 'item3'},
  ];

  it('check render:', () => {
    const wrapper = enzyme.mount(
      <DonutObjectKpi
        onObjectKpiChartTypeChange={(newType, showTitleRes, titleRes) => {
          chartType = newType;
          showTitle = showTitleRes;
          title = titleRes;
        }}
        showTitle={showTitle}
        chartType={chartType}
        title={title}
        objectId={obj}
        onCancel={() => cancelModal = true}
        submitModal={(data: DonutChartProps) => dataModal = data}
        onDashboardItemTypeChange={() => changeType = true}
      />,
    );
    expect(wrapper.find(InputLabeledField).length).toEqual(8);
    expect(wrapper.find(Table).length).toEqual(2);
    expect(wrapper.find(IconButton).length).toEqual(1);
    expect(wrapper.find(EnumDropDown).length).toEqual(9); // 4 self + 5 border table
  });

  it('check change value:', () => {
    const wrapper = enzyme.mount(
      <DonutObjectKpi
        onObjectKpiChartTypeChange={(newType, showTitleRes, titleRes) => {
          chartType = newType;
          showTitle = showTitleRes;
          title = titleRes;
        }}
        showTitle={showTitle}
        chartType={chartType}
        title={title}
        objectId={obj}
        onCancel={() => cancelModal = true}
        submitModal={(data: DonutChartProps) => dataModal = data}
        onDashboardItemTypeChange={() => changeType = true}
        data={{
          title,
          showTitle: true,
          selectors,
          chartType: ChartType.DONUT,
          type: PieChartType.KPI,
          dashboardItemType: DashboardItemType.OBJECT_KPI,
          interval: CHART_REFRESH_RATE,
          description,
        }}
      />,
    );
    wrapper.setState({
      resourceId: resourceObj,
      kpiDefinition: kpiDef,
      objectId: obj,
      selectors,
      title,
    });
    wrapper.update();
    wrapper.find(IconButton).last().simulate('click');
    expect(dataModal).not.toEqual(undefined);
    expect(dataModal!.title).toEqual(title);
    expect(dataModal!.description).toEqual(description);
    expect(dataModal!.chartType).toEqual(chartType);
    expect(dataModal!.selectors.length).toEqual(selectors.length);
    expect(dataModal!.dashboardItemType).toEqual(DashboardItemType.OBJECT_KPI);
  });

  it('check cancel modal:', () => {
    const newObj = {value: '2', label: 'item2'};
    const newResourceObj = {value: '3', label: 'item3'};
    const newKpiDef: KpiDefinition = {
      kpi: Kpi.HBASE_REGION_SERVER_NUM_OF_HLOG_FILE_20206,
      type: KpiDefinitionType.OBJECT_KPI,
      monitoringObject: {id: '4', presentation: 'item4'},
    };

    const newSelectors: NamedKpiSeriesSelector[] = [
      {kpi: Kpi.ACTIVE_DIRECTORY_COMPUTERS_COUNT, kpiDefinition: kpiDef, objectId: '1', objectIdName: 'item1'},
      {kpi: Kpi.ACTIVE_DIRECTORY_DISABLED_USERS_COUNT, kpiDefinition: kpiDef, objectId: '2', objectIdName: 'item2'},
      {kpi: Kpi.HBASE_REGION_SERVER_STORE_FILE_SIZE_20210, kpiDefinition: kpiDef, objectId: '3', objectIdName: 'item3'},
      {kpi: Kpi.HBASE_REGION_SERVER_NUM_OF_REGIONS_20204, kpiDefinition: kpiDef, objectId: '4', objectIdName: 'item4'},
    ];

    const wrapper = enzyme.mount(
      <DonutObjectKpi
        onObjectKpiChartTypeChange={(newType, showTitleRes, titleRes) => {
          chartType = newType;
          showTitle = showTitleRes;
          title = titleRes;
        }}
        showTitle={showTitle}
        chartType={chartType}
        title={title}
        objectId={newObj}
        onCancel={() => cancelModal = true}
        submitModal={(data: DonutChartProps) => dataModal = data}
        onDashboardItemTypeChange={() => changeType = true}
        data={{
          title,
          showTitle: true,
          selectors,
          chartType: ChartType.DONUT,
          type: PieChartType.KPI,
          dashboardItemType: DashboardItemType.OBJECT_KPI,
          interval: CHART_REFRESH_RATE,
          description,
        }}
      />,
    );
    wrapper.setState({
      resourceId: newResourceObj,
      kpiDefinition: newKpiDef,
      objectId: newObj,
      selectors: newSelectors,
      title,
    });
    wrapper.update();
    expect(dataModal!.selectors.length).toEqual(selectors.length);
    expect(cancelModal).toEqual(false);
    wrapper.find(Button).at(1).simulate('click');
    expect(dataModal!.selectors.length).not.toEqual(newSelectors.length);
    expect(cancelModal).toEqual(true);
  });

  it('check change type:', () => {
    const wrapper = enzyme.mount(
      <DonutObjectKpi
        onObjectKpiChartTypeChange={(newType, showTitleRes, titleRes) => {
          chartType = newType;
          showTitle = showTitleRes;
          title = titleRes;
        }}
        showTitle={showTitle}
        chartType={chartType}
        title={title}
        objectId={obj}
        onCancel={() => cancelModal = true}
        submitModal={(data: DonutChartProps) => dataModal = data}
        onDashboardItemTypeChange={() => changeType = true}
        data={{
          title,
          showTitle: true,
          selectors,
          chartType: ChartType.DONUT,
          type: PieChartType.KPI,
          dashboardItemType: DashboardItemType.OBJECT_KPI,
          interval: CHART_REFRESH_RATE,
          description,
        }}
      />,
    );
    wrapper.find(InputLabeledField).first().find(EnumDropDown).first().find('div').at(1).simulate('click');
    const type = wrapper.find(InputLabeledField).first().find(EnumDropDown).first();
    expect(changeType).toEqual(false);
    type.find(BuildOption).first().find(HorizontalLayout).first().find('div').first().simulate('click');
    expect(changeType).toEqual(true);
  });
});

【问题讨论】:

  • 我建议你做一些阅读搜索 jest 观察 memory-leak 这是你可以直接在文档中找到的东西:jestjs.io/docs/cli#--logheapusage,请再看看社区指南:@987654323 @

标签: node.js reactjs typescript jestjs enzyme


【解决方案1】:

对于任何可能遇到我的问题的人,我发现的解决方法是typescript 编译中排除所有测试文件。这是我的tsconfig.json 中的排除部分(我添加了最后两行):

"exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts",
    "src/**/*.test.ts",
    "src/**/*.test.tsx"
  ]

我应该提到,针对内存使用优化测试并没有帮助。

【讨论】:

    猜你喜欢
    • 2022-01-22
    • 2019-07-02
    • 2021-07-14
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2011-08-02
    相关资源
    最近更新 更多