ReferenceError:您正在尝试在 Jest 环境被拆除后“导入”一个文件

Posted

技术标签:

【中文标题】ReferenceError:您正在尝试在 Jest 环境被拆除后“导入”一个文件【英文标题】:ReferenceError: You are trying to `import` a file after the Jest environment has been torn down 【发布时间】:2018-11-20 11:27:01 【问题描述】:

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

运行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)

repl 链接

https://repl.it/repls/PartialGrimyMetadata

环境:

操作系统:Linux 4.14 节点:6.14.2 纱线:1.7.0 npm: 3.10.10 守望者:未找到 Xcode:不适用 android Studio:未找到

【问题讨论】:

【参考方案1】:

好的,找到了解决办法。

应该使用jest.useFakeTimers()

注意:将上面的代码放在测试文件中的 import 部分之后。

【讨论】:

我们在哪里使用它? @dopatraman 我在导入后的测试文件中使用了它。 (对吗?它奏效了。)但请参阅下面来自 TARJU 的关于它的使用。 如果你有一个 src__tests__\jestSetup.ts 更好地设置它,它将适用于每个测试。 很遗憾对我不起作用,我在测试文件中使用了 websocket 连接,但一直失败 在此处查看文档:jestjs.io/docs/timer-mocks【参考方案2】:

jest.useFakeTimers()

了解以上内容非常重要

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

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

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

【讨论】:

【参考方案3】:

我在使用 react-native-testing-library 测试 Apollo 时遇到了这个问题。

在这种情况下,有两个查询,一个父组件和一个子组件。父查询需要在子查询呈现并触发其查询之前解析。

解决方案是运行wait() 函数两次而不是一次。我认为双重触发对于确保两个查询都运行是必要的。不过,错误消息非常不透明。

test("...", () => 
  const rr = render(...);
  await wait();
  await wait(); // Child query must also run
  expect(...);


// Wait a tick so the query runs
// https://www.apollographql.com/docs/react/development-testing/testing/#testing-final-state
export async function wait(ms = 0) 
  await act(async () => 
    return new Promise(resolve => 
      setTimeout(resolve, ms);
    );
  );

【讨论】:

【参考方案4】:

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

afterAll(() =>  
  mongoose.connection.close()
)

也只是一次运行一个测试文件,例如,

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

【讨论】:

谢谢,添加--runInBand 参数为我解决了这个问题。 @Stan 欢迎您,感谢您的反馈。 此解决方案无法解决。我仍然有问题。 你可能想试试jest --detectOpenHandles --runInBand【参考方案5】:

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

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

afterEach(cleanup);

【讨论】:

【参考方案6】:

"testEnvironment": "jsdom" 添加到 package.json 或 jest.config.js 中的 jest 键中

"jest": 
  "testEnvironment": "jsdom",
  "preset": "react-native",
   ...

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

【讨论】:

除此之外,我还添加了afterEach(cleanup); 并且警告消失了。 :D【参考方案7】:

我想为答案做出贡献。

让我们看看错误信息

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

Torn down 意味着:Jest 已经完成运行,并且在 jest 被拆除或退出测试后,您的部分代码正在尝试执行。由于其异步性质,这在 javascript 上很常见。

有时它会发生在一个 Promise 回调被执行之后,例如:

import  someProcess from 'a-library'

task.job().then(result => 
    someProcess(result)
)

在上面的示例中,代码从a-library 导入someProcess

如果来自task 对象的方法job 花费的时间比jest 执行时间长,则它的回调(then() 调用)将在jest 之外运行,因为jest 一直在继续。因此,当someProcess 被执行时,它将从a-library 加载,所以 jest 会抱怨你在 jest 被撕裂后试图加载一个库。

标记为解决方案的答案部分正确,因为调用 jest.useFakeTimers() 将阻止您的代码等待您应该等待的 n 秒,调用 setTime 或类似方法使您的代码人为地 sincrhonoyus

让您的测试await 那些方法调用将帮助您更好地理解您的代码。

对我有用的代码是

describe("Some test set " , ()=>

    let heavyWorkinService = library.workingService();

// We are marking the test function call as async

     test(("Name of the test"), async  ()=>

// we are awaiting heavyWorkingService to done its job 
          await   hevyWorkingService("some data")
        )
)

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

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

【讨论】:

【参考方案8】:

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

import  Animated  from 'react-native';

Animated.timing = () => (
    start: () => jest.fn(),
);

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

...
  "jest": 
    ...,
    "setupFiles": [
      "<rootDir>/src/tests/jest-setup.js"
    ]
  ,
...

希望对大家有帮助

【讨论】:

【参考方案9】:

我在该文件的测试套件内的beforeEach() 方法中使用了jest.useFakeTimers()

beforeEach(() => 
    jest.useFakeTimers();
  );

【讨论】:

【参考方案10】:

我正在使用@testing-library/react-native。在我的测试用例中,我需要调用render(&lt;MyComponent/&gt;) 两次,所以我需要添加afterEach(cleanup) 这样才能解决问题。

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于ReferenceError:您正在尝试在 Jest 环境被拆除后“导入”一个文件的主要内容,如果未能解决你的问题,请参考以下文章

差异TypeError和ReferenceError

区别 TypeError 和 ReferenceError

ReferenceError:在初始化之前无法访问“步骤”

ReferenceError:尝试放置让公会时未定义消息

尝试将 Twilio 与 Meteor 一起使用,ReferenceError: Twilio is not defined

结果:ReferenceError:未定义响应