Capture errors out of scope with Mocha and Chai

I am modifying the node.js library to support true asynchronous operations.

I'm having problems with Mocha and Tea to pass this (similar) test.

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

The problem - because of nextTick - is that the error is thrown out of the scope of it , and in addition to the fact that the test does not work, Mocha also displays below.

 Uncaught Error: This is my error 

What is the right way to structure this test to succeed?

+6
source share
2 answers

Hmm ... in a full-featured application, what would I do, probably use something like Sinon to verify that the method that should throw the error was called and thrown.

In code in which you cannot do this, the following method may block the exception:

 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'); }); }); }); 

This code creates the "domain" stored in d . The domain will generate error events on uncaught exceptions that occur in it, so we run a test inside the domain ( d.run(...) ) that we created and expect an exception to occur ( d.on('error', ... ). We check that this is an error object. (In the real test, I also checked the error message.) When we finish, we call done() to tell Mocha that the asynchronous test has completed.

The error event handler calls d.exit() . This should ensure that Mocha can break the error normally if the statement ( expect(err instanceof Error) ...) fails. If we do not leave the domain, the domain will delay the error. In addition, the check itself should be performed at the next tick located outside the domain d .

Uses domain Problem?

NO!

The documentation for domain contains some warnings about disabling operations after an uncaught exception is caught while starting the current process, such as a server . Then you need to do to clear what you can clear and exit as soon as possible. However, using domain in the test is no different from what Mocha does. The way Mocha catches unhandled exceptions in asynchronous code is using process.on('uncaughtException' . After detecting an unhandled exception, Mocha will mark the current test as unsuccessful and continue. However, the documentation regarding uncaughtException says: “Do not use it, use domains instead . use it, restart the application after each unhandled exception! "

Ergo, anyone who has a problem using domain should not use Mocha in the first place .

+3
source

You are trying to catch an exception from the wrong function, a container for the function that throws. Also, since the function terminates in nextTick, it executes on another stack, and therefore the exception cannot be caught (this, unfortunately, is just a JS thing).

Try this instead:

 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(); }); }); 

Update. There is no proper way to structure this test to pass, because you cannot catch an exception in this scenario. Perhaps update your code to use callbacks to handle errors:

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

Source: https://habr.com/ru/post/977669/


All Articles