我的 Jests 测试正在泄漏内存,我该如何解决这个问题?

问题描述 投票:0回答:9

当我运行笑话测试时,每个测试使用的内存量会随着时间的推移而增加。这个问题在我的本地机器上并不明显;相反,我在 CircleCI 上运行测试时发现了这一点。我收到以下错误:

 FAIL  __tests__/pages/login.test.tsx
 
  ● Test suite failed to run
 
    jest: failed to cache transform results in: /tmp/jest_2ne/jest-transform-cache-7bdebd1a0c578519274d14a78b89f87c-f8238a99880aac6151736010e575fab1/0b/symbols_0bf4cffb45cb261625f2f3fca21a4789.map
 
    Failure message: ENOMEM: not enough memory, write
 
      at writeFileSync (node_modules/write-file-atomic/index.js:215:10)
      at writeCacheFile (node_modules/@jest/transform/build/ScriptTransformer.js:809:33)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:554:7)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:586:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:624:25)

如何修复我的笑话配置以防止出现这种情况?

node.js reactjs memory jestjs
9个回答
33
投票

首先,通过使用以下选项运行 jest 来确保您进行了泄漏测试:

jest --logHeapUsage

运行测试并检查内存消耗是否随着时间的推移而增加,如下所示(文件名已更改):

PASS  __tests__/pages/file.test.tsx (181 MB heap size)
 PASS  __tests__/pages/file2.test.tsx (193 MB heap size)
 PASS  __tests__/components/Header/file3.test.tsx (201 MB heap size)
 PASS  __tests__/components/Header/file4.test.tsx (192 MB heap size)
 PASS  __tests__/components/Header/file5.test.tsx (218 MB heap size)
 PASS  __tests__/pages/file6.test.tsx (201 MB heap size)
 PASS  __tests__/components/file6.test.tsx (203 MB heap size)
 PASS  __tests__/components/file7.test.tsx (213 MB heap size)
 PASS  __tests__/components/file8.test.tsx (234 MB heap size)
 PASS  __tests__/components/file9.test.tsx (222 MB heap size)
 PASS  __tests__/components/file10.test.tsx (240 MB heap size)
 PASS  __tests__/components/file11.test.tsx (231 MB heap size)
 PASS  __tests__/utils/file12.test.tsx (239 MB heap size)
 PASS  __tests__/components/file13.test.tsx (251 MB heap size)
 PASS  __tests__/components/file14.test.tsx (239 MB heap size)
 PASS  __tests__/components/file15.test.tsx (249 MB heap size)
 PASS  __tests__/components/file16.test.tsx (143 MB heap size)

要解决此问题,请将

npm run test
中的
yarn test
package.json
命令更改为:
node --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage

运行命令。这是我的输出:

 PASS  __tests__/components/file.test.tsx (143 MB heap size)
 PASS  __tests__/pages/onboarding/file1.test.tsx (149 MB heap size)
 PASS  __tests__/components/file2.test.tsx (146 MB heap size)
 PASS  __tests__/components/file3.test.tsx (146 MB heap size)
 PASS  __tests__/components/file4.test.tsx (153 MB heap size)
 PASS  __tests__/components/Header /file5.test.tsx (149 MB heap size)
 PASS  __tests__/pages/file6.test.tsx (149 MB heap size)
 PASS  __tests__/pages/file7.test.tsx (149 MB heap size)
 PASS  __tests__/components/file8.test.tsx (147 MB heap size)
 PASS  __tests__/components/file9.test.tsx (148 MB heap size)
 PASS  __tests__/pages/file10.test.tsx (148 MB heap size)
 PASS  __tests__/components/Header /file11.test.tsx (148 MB heap size)
 PASS  __tests__/functions/file12.test.tsx (149 MB heap size)
 PASS  __tests__/components/file13.test.tsx (148 MB heap size)
 PASS  __tests__/components/file14.test.tsx (150 MB heap size)
 PASS  __tests__/components/file15.test.tsx (150 MB heap size)
 PASS  __tests__/components/Header /file16.test.tsx (149 MB heap size)
 PASS  __tests__/components/file17.test.tsx (149 MB heap size)
 PASS  __tests__/utils/file18.test.tsx (150 MB heap size)
 PASS  __tests__/components/file19.test.tsx (149 MB heap size)
 PASS  __tests__/pages/file20.test.tsx (150 MB heap size)

如您所见,内存消耗更加一致。

您可以在这个 Github 问题中阅读有关此问题和解决方案的更多信息,其中描述了 jest 的垃圾收集器泄漏问题。


20
投票

我在运行集成测试时遇到了同样的问题,最初堆大小约为 160MB,本地爬升至约 1600MB,并在 CI 中出现 OOM。这个问题还导致随机测试开始失败,并显示

Exceeded timeout of 5000 ms for a test.

有关此问题的主要讨论可以在此处找到,在顶部您可以找到快速修复该问题。要修复此问题,您必须在配置中设置
workerIdleMemoryLimit
标志:

// jest.config.js

/** @type {import('jest').Config} */
const config = {
    workerIdleMemoryLimit: '512MB',
};

module.exports = config;

环境:

  • 节点:16.15.0
  • 开玩笑:29.5.0
  • ts-笑话:29.0.5

更改配置后,堆大小保持在限制以下并修复了超时失败问题。
作为额外的好处,测试在本地运行速度更快约 20 秒,在 CI 中运行速度约 4 分钟(使用

--maxWorkers 4
cli 选项)


12
投票

您可以使用

jest -w 1
来避免这些内存问题。

有关 Jest CLI 文档的更多信息

--maxWorkers=|# 别名:-w.指定工作池为运行测试而生成的最大工作人员数量。在单次运行中 模式,默认为您的可用核心数 机器主线程减一。在观看模式下,默认为 机器上一半的可用内核,以确保 Jest 不引人注目,不会让您的机器停止运转。可能是 在 CI 等资源有限的环境中调整这一点很有用,但是 默认值应该足以满足大多数用例。


7
投票

我的环境是:

  • 节点18.12.1
  • 开玩笑29.3.1
  • ts-笑话29.0.3

我运行测试的 npm 脚本是

jest --coverage
。当我运行测试时,出现此错误

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

使用

v8
作为承保提供商对我有用。

// Example jest.config.js
module.exports = {
    coverageProvider: 'v8', // Default is 'babel'
    transform: {
        '\\.[jt]sx?$': 'ts-jest'
    }
};

参考。 https://jestjs.io/docs/configuration#coverageprovider-string


3
投票

就我而言,当我使用复杂对象时就会发生这种情况:

expect(spyFn).toHaveBeenCalledWith(COMPLEX_OBJECT_WITH_DIFFICULT_STRUCTURE);

因此,当您使用 jest toEqual 实用程序时,您可能会遇到 堆内存不足错误(它递归地比较对象的所有属性)。

作为解决方案,尝试用“simplifiedObject”替换“complexObject”:

  • expect.objectContaining({ ...someOfComplexObjectProps })
  • expect.any(对象)

2
投票

切换到节点版本 16.10 解决了我的问题。显然,jest 的内存泄漏仅发生在节点版本 > 16 的情况下。 我只是使用 NVM 通过运行

nvm install 16.10
首先安装节点 16.10。完成此操作后,运行我的玩笑测试使用了 555MB,而不是 1.5GB 内存。


2
投票

我尝试了一些不同的解决方案,但对我不起作用:

    增加
  • --max-old-space-size
    
    
  • 使用节点标志:
  • node --no-compilation-cache
    
    
  • 使用
  • --runInBand
    
    
  • 使用
  • --expose-gc
    
    
  • 限制工人数量
什么

做了对我有用:

限制每个worker的空闲内存

我还限制了工人的数量,所以也许这是解决方案的组合。


1
投票
如果它对其他人有帮助:

什么对我不起作用:

  • --max-old-space-size
    
    
  • --no-compilation-cache
    
    
  • --runInBand
    
    
  • --expose-gc
    
    
  • --maxWorkers
    
    
  • --workerIdleMemoryLimit
    
    
最终效果如何:

  • --clearMocks
    
    
(将

jest.clearAllMocks()

 添加到每个套件上的 
beforeEach
 的结果相同)

在这一个上绕了一圈房子 -

workerIdleMemoryLimit

似乎只在套件之间工作,而不是在每次测试之间工作(
根据文档)所以也通过设置它并分割我的较大套件来使其工作,但并不高兴以此作为最终修复。


0
投票
我已经尝试了上面提到的许多方法和其他解决方案,但没有成功,请执行以下配置,如果仍然不起作用,升级节点会有所帮助,它会正常工作。

这将有助于加速测试运行和解决堆内存问题

  1. 在 jest 命令中添加

    --workerIdleMemoryLimit=350

    ,如下所示

    jest --env=jsdom --verbose a --coverage --max-old-space-size=16384 --silent --logHeapUsage --workerIdleMemoryLimit=350

根据您的系统配置更改workerIdleMemoryLimit的值

  1. 在 jest 配置转换属性中添加

    isolatedModules: true

    ,如下所示

    变换:{ '^.+\.ts?$': ['ts-jest', { 隔离模块:true }] }

© www.soinside.com 2019 - 2024. All rights reserved.