ReferenceError:您试图在Jest环境被拆除后"导入"文件

nri*_*ion 14 javascript reactjs jestjs react-native enzyme

我有一个组件,它使用Animated来自react native 的组件.我开始编写一个测试用例来模拟onPress一个组件,它调用一个包含Animated.timing在其中的函数setState.

运行jest正常,但测试永远不会停止运行,我之前写过的一个不相关的测试用例现在似乎永远不会通过(之前通过).

运行jest --watch,我收到此错误:

ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.

      at Function.bezier (node_modules/react-native/Libraries/Animated/src/Easing.js:113:21)
      at ease (node_modules/react-native/Libraries/Animated/src/Easing.js:34:24)
      at TimingAnimation._easing (node_modules/react-native/Libraries/Animated/src/Easing.js:133:18)
      at TimingAnimation.onUpdate (node_modules/react-native/Libraries/Animated/src/animations/TimingAnimation.js:107:45)

 RUNS  src/__tests__/SlideDownMenu.test.js

/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/Easing.js:114
      return _bezier(x1, y1, x2, y2);
             ^
TypeError: _bezier is not a function
    at Function.bezier (/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/Easing.js:224:12)
    at ease (/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/Easing.js:94:21)
    at TimingAnimation._easing (/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/Easing.js:255:16)
    at TimingAnimation.onUpdate (/home/nrion/Desktop/mobile-ui/PriceInsight_app/node_modules/react-native/Libraries/Animated/src/animations/TimingAnimation.js:138:14)
    at ontimeout (timers.js:386:11)
    at tryOnTimeout (timers.js:250:5)
    at Timer.listOnTimeout (timers.js:214:5)
Run Code Online (Sandbox Code Playgroud)

链接到repl

https://repl.it/repls/PartialGrimyMetadata

环境:

  • 操作系统:Linux 4.14
  • 节点:6.14.2
  • 纱线:1.7.0
  • npm:3.10.10
  • 守望者:未找到
  • Xcode:N/A.
  • Android Studio:未找到

Jua*_*dor 38

我愿意为答案做出贡献。

好吧,让我们看看错误消息

ReferenceError: You are trying to 'import' a file after the Jest environment has been torn down.

拆除意味着:Jest 已经完成运行,并且您的代码的某些部分正在尝试在 jest 已经完成运行测试后执行。由于其异步特性,这在 Javascript 上很常见。

有时它会在执行承诺回调后发生。例如:

import { someProcess } from 'a-library'

task.job().then(result => {
    someProcess(result)
})
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,代码someProcessa-library.

job如果对象中的方法task花费的时间比 jest 执行的时间长,则其回调(then()调用)将在 jest 之外运行,因为 jest 已经完成运行测试。因此,当someProcess执行时,它将被加载,a-library因此 jest 会抱怨您在 jest 被拆除后试图加载库。

标记为解决方案的答案部分正确,因为调用jest.useFakeTimers()将阻止您的代码等待n您在调用或类似情况下应该等待的秒数setTime,从而使您的代码人为同步。

测试await这些方法调用将帮助您更好地了解错误是在哪里引入的。

对我有用的代码是

describe("Some test set", () => {
  let heavyWorkingService = library.workingService();

   // We are marking the test function call as async
   test(("Name of the test"), async  () => {

     // we are awaiting heavyWorkingService to finish its job
     await heavyWorkingService("some data")
   })
})

Run Code Online (Sandbox Code Playgroud)

在我的真实场景中,我的代码是从 firebase 获取数据,并且因为我没有使用模拟进行此测试,所以它在读取的数据返回后尝试导入 firebase .get()。将测试标记为async并使用关键字调用方法await解决了我的问题

当然,有很多方法可以处理这个错误,只是想让您知道这个错误背后的真正原因,以便您可以为您的测试找到正确的解决方案!


TAR*_*RJU 28

jest.useFakeTimers()

有了上面,理解这一点非常重要

jest.useFakeTimers() 使用模拟函数模拟 setTimeout 和其他计时器函数。

如果在一个文件或描述块中运行多个测试, jest.useFakeTimers(); 可以在每次测试之前手动调用或使用设置函数(例如 beforeEach)调用。

不这样做将导致内部使用计数器不被重置。


nri*_*ion 17

好的,找到了解决方案.

应该用 jest.useFakeTimers()

  • 如果你有一个 src\__tests__\jestSetup.ts 最好将其设置在那里,它将适用于每个测试。 (6认同)
  • 我们在哪里使用呢? (4认同)
  • @dopatraman 我在导入后在测试文件中使用了它。(这是正确的吗?它起作用了。)但是请参阅下面的 TARJU 关于其使用的信息。 (2认同)

Sec*_*Son 8

我正在使用@testing-library/react-native,所以我所做的是在安装文件中使用清理。

// jest.setup.js
import { cleanup } from '@testing-library/react-native';

afterEach(cleanup);

Run Code Online (Sandbox Code Playgroud)

  • 您需要对 beforeAll、afterAll、afterEach 等使用 setupFilesAfterEnv (2认同)

jdk*_*jdk 7

在 jest 测试文件的最后添加以下几行,毕竟测试是编写的。

afterAll(() => { 
  mongoose.connection.close()
})
Run Code Online (Sandbox Code Playgroud)

并且一次只运行一个测试文件,例如,

> jest --verbose --runInBand -- filename.test.js

  • 谢谢,添加 `--runInBand` 参数为我解决了这个问题。 (3认同)

Rus*_*eev 7

以上都不适合我。我的解决方案是在jest-setup.js文件中添加以下代码:

import { Animated } from 'react-native';

Animated.timing = () => ({
    start: () => jest.fn(),
});
Run Code Online (Sandbox Code Playgroud)

不要忘记将此文件包含到您的package.json jest 配置中:

...
  "jest": {
    ...,
    "setupFiles": [
      "<rootDir>/src/tests/jest-setup.js"
    ]
  },
...
Run Code Online (Sandbox Code Playgroud)

我希望它能帮助任何人


Gia*_* P. 5

在 package.json 或 jest.config.js 中添加"testEnvironment": "jsdom"jestkey

"jest": {
  "testEnvironment": "jsdom",
  "preset": "react-native",
   ...
Run Code Online (Sandbox Code Playgroud)

取自:https : //stackoverflow.com/a/64567257/728287


rev*_*evy 5

jest.useFakeTimers这对我来说不是一个选择,因为它会阻止我正在使用的其他库的执行。

我的解决方法是在每次测试后添加一个延迟,以便任何异步操作都有时间在 Jest 环境被拆除之前完成:

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

describe('Test suite', () => {
  
  // Give time to any async operation to complete after each test
  afterEach(async () => {
    await sleep(2000);
  });

  // Also close any pending connection (or related) if any
  afterAll(async () => {
    await closeConnections();
  });

  it('My test', async () => {
    // Test...
  });
});
Run Code Online (Sandbox Code Playgroud)

当然,必须根据您的应用调整延迟时间。