rxjs - 在 RxJS observable 的 subscribe() 中,Jest 没有处理来自 expect() 的错误

标签 rxjs jestjs rxjs6

我一直在尝试让 Jest 与 RxJS 一起工作,但遇到了 Jest 无法从订阅回调内部传播错误的问题。

这是我尝试过但不起作用的示例测试:

import {of} from 'rxjs';

test('should fail', () => {
  of(false).subscribe(val => {
    expect(val).toBe(true);
  });
});

上面的测试应该会失败,但它通过了。我用谷歌搜索并找到了以下解决方案:
  • Failing expect() inside subscribe() does not mark test as invalid

  • 这建议在玩笑中使用“完成”语法来解决问题。虽然使用“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);
    });
    

    必须使用异步语义来解决同步测试的问题似乎很奇怪。

    想知道是否有人提出了在 rxjs 中进行测试的好的解决方案,这将导致 expect调用由测试库正确处理。

    提前致谢!

    package.json 中的相关依赖:

     "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"
      }
    

    .babelrc 文件

    {
      "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"
      ]
    }
    

    最佳答案

    想通了问题!把这个留在这里给遇到类似问题的人。 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();
    });
    

    如果您不需要模拟计时器,则无需添加它们。我认为即使我可以验证代码是否被同步调用,假计时器也是一个问题,这有点奇怪。如果有人对为什么会出现这种情况的实现细节有更深入的了解,我希望得到一些解释。

    关于rxjs - 在 RxJS observable 的 subscribe() 中,Jest 没有处理来自 expect() 的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53826430/

    相关文章:

    javascript - RxJS - 检测长鼠标按下

    node.js - 使用 supertest 和 mongoose 时,Jest 在测试运行完成后一秒没有退出

    angular - 我应该为不同的订阅使用多个 BehaviorSubject 吗?

    node.js - 使用数据库进行自动化测试

    rxjs - BehaviorSubject 映射一个 BehaviorSubject

    angular - 响应 rxjs 取消订阅

    javascript - 当状态发生任何变化/选择器的内存不起作用时,NgRx 选择器会发出

    javascript - Rxjs 如何知道可观察到的订阅者有多少?

    javascript - RxJS 自定义运算符不调用完成

    javascript - 使用 Jest 的 setTimeout 测试 Promise