如何防止 Mocha 捕获未处理的异常?

Lou*_*uis 5 javascript mocha.js addeventlistener

我正在为一个库编写一个测试套件,该套件执行处理未由catch语句处理的异常。该库侦听error滴到全局范围内的事件(例如window.addEventListener("error", ...))。

但是,如果我想测试它是否真的能够检测到未处理的异常,我不能,因为 Mocha 将此类异常视为测试失败。我不能使用像断言expect(foo).to.throw,因为如果我使用这些,那么异常被捕获expect,不再一个未处理的异常:它不会引发全球的听众,我的图书馆安装和我想测试。

我试过了,allowUncaught但这并没有解决问题。这是一个重现问题的示例测试:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8"/>
    <link href="node_modules/mocha/mocha.css" type="text/css" media="screen" rel="stylesheet" />
    <script src="node_modules/mocha/mocha.js"></script>
  </head>
  <body>
    <div id="mocha"></div>
    <script>
      mocha.setup('bdd');
      mocha.allowUncaught();

      it("should be fine", function (done) {
        // Simulate an error thrown by asynchronous code.
        setTimeout(function () {
          throw new Error("error");
        }, 100);

        // My actual error handler is bigger than this. This is just to
        // simulate what my actual test suite does.
        function listener(ev) {
          // Uninstall ourselves.
          window.removeEventListener("error", listener);
          done(); // We detected the error: everything is fine.
        }
        window.addEventListener("error", listener);
      });

      mocha.run();
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

上面的测试应该可以通过。但是,当我运行它时,Mocha 报告一失败一成功!如何让 Mocha 忽略未捕获的异常并让我的自定义代码处理它?

Lou*_*uis 6

Mocha 安装了自己的未处理异常事件监听器window并且allowUncaught不会阻止它。您需要做的是使用以下命令卸载此处理程序:

Mocha.process.removeListener("uncaughtException");
Run Code Online (Sandbox Code Playgroud)

下面是一个暂时关闭 Mocha 的未处理异常处理的示例:

  mocha.setup('bdd');
  mocha.allowUncaught();

  var savedHandler = undefined;
  before(function () {
    // Save Mocha's handler.
    savedHandler = window.onerror;
  });

  describe("without handler", function () {
    before(function () {
      // Stop Mocha from handling uncaughtExceptions.
      Mocha.process.removeListener("uncaughtException");
    });

    it("should be fine", function (done) {
      setTimeout(function () {
        throw new Error("error");
      }, 100);

      function listener(ev) {
        window.removeEventListener("error", listener);
        done();
      }
      window.addEventListener("error", listener);
    });

    after(function () {
      // Restore the handler so that the next tests are treated as
      // mocha treats them.
      window.onerror = savedHandler;
    });
  });

  describe("with handler", function () {

    it("should fail", function (done) {
      setTimeout(function () {
        throw new Error("error");
      }, 100);
    });
  });

  mocha.run();
Run Code Online (Sandbox Code Playgroud)

第一次测试将通过,并且仅计算一次。正如我们所期望的,第二个测试将失败,因为 Mocha 的未处理异常处理程序已生效。

尽管只有一次测试,但一次通过一次失败的原因是 Mocha 的特殊性。它检测到未处理的异常,因此声明测试失败。但随后您的代码会调用done,因此 Mocha 声明测试已通过并对其进行两次计数。

请注意,上面使用的方法没有记录,并且可能会随着 Mocha 的未来版本而中断。据我所知,没有“官方”方法可以得到预期的结果。