Node.js has a useful built-in testing tool, the assert module. Its functionality is similar to assert libraries in other languages. Namely, it's a collection of functions for testing conditions, and if the conditions indicate an error, the assert function throws an exception.
At its simplest, a test suite is a series of assert calls to validate the behavior of a thing being tested. For example, a test suite could instantiate the user authentication service, then make an API call, using assert methods to validate the result, then make another API call, validating its results, and so on.
Consider a code snippet like this, which you could save in a file named deleteFile.js:
const fs = require('fs');
exports.deleteFile = function(fname, callback) {
fs.stat(fname, (err, stats) => {
if (err) callback(new Error(`the file ${fname} does not exist`));
else {
fs.unlink(fname, err2 => {
if (err) callback(new Error(`could not delete ${fname}`));
else callback();
});
}
});
};
The first thing to notice is this contains several layers of asynchronous callback functions. That presents a couple of challenges:
- Capturing errors from deep inside a callback, to ensure the test scenario fails
- Detecting conditions where the callbacks are never called
The following is an example of using assert for testing. Create a file named test-deleteFile.js containing the following:
const fs = require('fs');
const assert = require('assert');
const df = require('./deleteFile');
df.deleteFile("no-such-file", (err) => {
assert.throws(
function() { if (err) throw err; },
function(error) {
if ((error instanceof Error)
&& /does not exist/.test(error)) {
return true;
} else return false;
},
"unexpected error"
);
});
This is what's called a negative test scenario, in that it's testing whether requesting to delete a nonexistent file throws an error.
If you are looking for a quick way to test, the assert module can be useful when used this way. If it runs and no messages are printed, then the test passes. But, did it catch the instance of the deleteFile callback never being called?
$ node test-deleteFile.js
The assert module is used by many of the test frameworks as a core tool for writing test cases. What the test frameworks do is create a familiar test suite and test case structure to encapsulate your test code.
There are many styles of assertion libraries available in Node.js. Later in this chapter, we'll use the Chai assertion library (http://chaijs.com/) which gives you a choice between three different assertion styles (should, expect, and assert).