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.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)
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(<MyComponent/>)
两次,所以我需要添加afterEach(cleanup)
这样才能解决问题。
【讨论】:
正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。以上是关于ReferenceError:您正在尝试在 Jest 环境被拆除后“导入”一个文件的主要内容,如果未能解决你的问题,请参考以下文章
尝试将 Twilio 与 Meteor 一起使用,ReferenceError: Twilio is not defined