我一直在尝试让 Jest 与 RxJS 一起工作,但遇到了 Jest 无法从订阅回调内部传播错误的问题。
这是我尝试过但不起作用的示例测试:
import {of} from 'rxjs';
test('should fail', () => {
of(false).subscribe(val => {
expect(val).toBe(true);
});
});
Run Code Online (Sandbox Code Playgroud)
上面的测试应该会失败,但它通过了。我用谷歌搜索并找到了以下解决方案:
这建议在玩笑中使用“完成”语法来解决问题。虽然使用“done”回调确实会使上述测试失败,但这种方法存在许多问题:
测试失败,因为 subcribe() 中的 'expect' 调用抛出错误,导致 'done()' 永远不会被调用。然后测试超时,等待完成。因此,它不是传播“期望”错误,而是导致超时错误,这意味着在期望子句中失败的每个测试都将显示超时错误,而不是“期望”调用失败的实际错误消息。
因为所有测试都由于超时错误而失败,这意味着每个测试需要 5 秒才能失败(异步测试在 5 秒后超时)。这会显着增加测试运行的时间
该done回调是为了支持异步用例测试。但是 rxjs 不一定是异步的。我上面内联的代码实际上是同步运行的。例如,以下测试将通过:
import {of} from 'rxjs';
test('should pass', () => {
let didRunSynchronously = false;
of(true).subscribe(() => {
didRunSynchronously = true;
});
expect(didRunSynchronously).toBe(true);
});
Run Code Online (Sandbox Code Playgroud)
必须使用异步语义来解决同步测试的问题似乎很奇怪。
想知道是否有人提出了在 rxjs 中进行测试的好解决方案,这将导致expect测试库正确处理调用。
提前致谢!
"dependencies": {
"@babel/polyfill": "^7.0.0",
"classnames": "^2.2.6",
"history": "^4.7.2",
"json-stringify-pretty-compact": "^1.2.0",
"minimist": "^1.2.0",
"normalize.css": "^8.0.0",
"nullthrows": "^1.1.0",
"react": "^16.5.2",
"react-dom": "^16.5.2",
"react-router-dom": "^4.3.1",
"rxjs": "^6.3.3",
},
"devDependencies": {
"@babel/core": "^7.2.2",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/preset-env": "^7.1.0",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"babel-core": "^7.0.0-bridge.0",
"babel-env": "^2.4.1",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-loader": "^8.0.4",
"copy-webpack-plugin": "^4.5.3",
"css-loader": "^1.0.0",
"eslint": "^5.9.0",
"eslint-plugin-flowtype": "^3.2.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-react": "^7.11.1",
"eslint-watch": "^4.0.2",
"flow-bin": "^0.83.0",
"html-webpack-plugin": "^3.2.0",
"jest": "^23.6.0",
"prettier": "^1.15.3",
"style-loader": "^0.23.1",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.9"
}
Run Code Online (Sandbox Code Playgroud)
{
"plugins": [
"module:@babel/plugin-proposal-class-properties",
"module:@babel/plugin-proposal-object-rest-spread"
],
"presets": [
["module:@babel/preset-env", { "targets": { "node": "6.10" } }],
"module:@babel/preset-flow"
]
}
Run Code Online (Sandbox Code Playgroud)
即使我几年后才讨论这个主题,这也可能会帮助其他刚开始测试异步代码的人。例如,请参阅https://jestjs.io/docs/asynchronous并在订阅结束时使用 done() 回调。如果不执行此回调,由于之前的错误,测试将按预期失败。
it('should fetch the right data', done => {
fetchData().subscribe(data => {
expect(data).toBe('expected data');
done();
});
});
Run Code Online (Sandbox Code Playgroud)
找出问题所在了!将此留给遇到类似问题的任何人。RxJS 和 Jest 工作正常并正确传播错误。问题是我在测试脚本中添加了“jest.useFakeTimers”调用。由于某种原因,这导致错误在测试中无法正确传播。我需要添加“jest.runAllTimers”来引发错误。这是正确实现的完整测试脚本:
import {of} from 'rxjs';
jest.useFakeTimers();
test('should fail', () => {
of(false).subscribe(val => {
expect(val).toBe(true);
});
jest.runAllTimers();
});
Run Code Online (Sandbox Code Playgroud)
如果您不需要模拟计时器,则无需添加它们。我认为假计时器是一个问题有点奇怪,尽管我可以验证代码是否被同步调用。如果有人对为什么会出现这种情况的实现细节有更多的了解,我会很感激一些解释。
| 归档时间: |
|
| 查看次数: |
2940 次 |
| 最近记录: |