Mocha和Chai发现了超出范围的错误

Catching out-of-scope errors with Mocha and Chai

本文关键字:范围 错误 Chai 发现 Mocha      更新时间:2023-09-26

我正在修改node.js库以支持真正的异步操作。

我遇到了Mocha和Chai的麻烦,让这个(类似的)测试通过

it('should throw an error', function() {
    expect(function() {
        process.nextTick(function() {
            throw new Error('This is my error');
        });
    }).to.throw(Error);
});

问题是,由于nextTick,Error被抛出it的范围之外,除了测试失败外,Mocha还输出以下内容。

Uncaught Error: This is my error

为了使测试成功,构建测试的正确方法是什么?

嗯。。。在一个成熟的应用程序中,我可能会使用类似Sinon的方法来检查应该抛出错误的方法是否已被调用并正在抛出。

在无法执行此操作的代码中,以下方法将捕获异常:

var expect = require("chai").expect;
var domain = require("domain");
it('should throw an error', function(done) {
    var d = domain.create();
    d.on('error', function (err) {
        // Exit the current domain.
        d.exit();
        // We must execute this code at the next tick.
        process.nextTick(function () {
            console.log(err); // Just to show something on the console.
            expect(err instanceof Error).to.be.true;
            done();
        });
    });

    d.run(function () {
        process.nextTick(function() {
            throw new Error('This is my error');
        });
    });
});

此代码创建一个存储在d中的"域"。域将对发生在其中的未捕获异常发出error事件,因此我们在创建的域(d.run(...))内运行测试,并等待异常发生(d.on('error', ...)。我们检查它是否是Error对象。(在实际测试中,我也会检查错误消息。)当我们完成时,我们调用done()来告诉Mocha异步测试已经结束。

error事件的处理程序调用d.exit()。这是为了让Mocha在断言(expect(err instanceof Error)…)失败时能够正常捕捉错误。如果我们不退出域,那么域将捕获错误。此外,检查本身必须在d域之外的下一个刻度上执行。

使用domain是个问题吗

domain的文档附带了一些关于在运行正在进行的进程(如服务器)时捕获到未捕获的异常时关闭操作的警告。然后要做的是清洁可以清洁的东西,并尽快离开然而,在测试中使用domain与Mocha已经在做的没有什么不同Mocha在异步代码中捕获未处理异常的方法是使用process.on('uncaughtException'。在捕捉到未处理的异常时,Mocha将当前测试标记为失败并继续。然而,关于uncaughtException的文档说:"不要使用它,请使用domains。如果确实使用了它,请在每次未处理的异常后重新启动应用程序!"

Ergo,任何对使用domain有问题的人首先都不应该使用Mocha

您试图在不正确的函数上捕获异常,该函数是抛出函数的容器。此外,由于函数被封装在nextTick中,它在不同的堆栈中执行,因此无法捕获异常(不幸的是,这只是JS的事情)。

试试这个:

it ('should throw an error', function (done) {
  process.nextTick(function () {
    var myFn = function () { throw new Error() };
    expect(myFn).to.throw(Error);
    // Tell mocha the test is complete 
    done();
  });
});

更新:由于在这种情况下无法捕获异常,因此没有适当的方法来构建此测试以使其通过。也许更新您的代码以使用回调来处理错误:

function doSomethingUnsafe() {
  try {
    // Run code here that may cause exceptions...
    callback(null, 'Woohoo! No errors!');
  } catch (e) {
    callback (e, null);
  }
}