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

时间:2016-09-06 17:03:35

标签: javascript mocha 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>

上述测试应该通过。然而,当我运行它时,摩卡报告了一次失败和一次成功!如何让Mocha忽略未捕获的异常并让我的自定义代码处理它?<​​/ p>

2 个答案:

答案 0 :(得分:4)

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

Mocha.process.removeListener("uncaughtException");

这是暂时关闭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();

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

即使您只有一次测试,您获得一次通过和一次失败的原因是Mocha的一种特殊性。它检测未处理的异常,因此声明测试失败。但然后你的代码调用done所以Mocha声明测试已经过去并计算两次。

请注意,上面使用的方法没有记录,可能会破坏未来的Mocha版本。据我所知,没有&#34;官方&#34;获得理想结果的方法。

答案 1 :(得分:-2)

在我看来,你真正反对的是一个设计问题。全球国家是单位测试的毒药。您必须摆脱对window的硬编码依赖关系,以使您的代码易于测试。

也许你可以在实例化时让你的组件接受一个对象来附加自己。然后你可以测试agaist任意DOM元素。

或者,如果要对窗口对象进行测试,只需传入另一个窗口对象即可。您可以生成一个子窗口并使用它。摩卡应该没问题。 (拿着一点盐,我在我的一些测试中创建了子窗口,但是我没有在它们中触发未处理的异常。)