
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
99 lines
3.5 KiB
Plaintext
99 lines
3.5 KiB
Plaintext
== Why is this an issue?
|
|
|
|
It is not good enough to test if an exception is raised, without checking which exception it is. Such tests will not be able to differentiate the expected exception from an unexpected one. They should instead validate the exception message and/or type.
|
|
|
|
|
|
This rule raises an issue in the following cases:
|
|
|
|
* When an asynchronous Mocha test calls the ``++done()++`` callback, without parameters, in a ``++catch++`` block and there is no reference to the caught exception in this block. Either the error should be passed to ``++done()++`` or the exception should be checked further.
|
|
* When Chai assertions are used to test if a function throws any exception, or an exception of type ``++Error++`` without checking the message.
|
|
* When Chai assertions are used to test if a function does not throw an exception of type ``++Error++`` without checking the message.
|
|
|
|
Rule doesn't raise an issue when assertion is negated using `not`, it such case the exception doesn't need to be specific.
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,javascript]
|
|
----
|
|
const expect = require("chai").expect;
|
|
const fs = require("fs");
|
|
|
|
describe("exceptions are not tested properly", function() {
|
|
const funcThrows = function () { throw new TypeError('What is this type?'); };
|
|
const funcNoThrow = function () { /*noop*/ };
|
|
|
|
it("forgot to pass the error to 'done()'", function(done) {
|
|
fs.readFile("/etc/zshrc", 'utf8', function(err, data) {
|
|
try {
|
|
expect(data).to.match(/some expected string/);
|
|
} catch (e) { // Noncompliant
|
|
// Either the exception should be passed to done(e), or the exception should be tested further.
|
|
done();
|
|
}
|
|
});
|
|
});
|
|
|
|
it("does not 'expect' a specific exception", function() {
|
|
expect(funcThrows).to.throw(); // Noncompliant
|
|
// Error is not precise enough
|
|
expect(funcThrows).to.throw(Error); // Noncompliant
|
|
});
|
|
});
|
|
----
|
|
|
|
=== Compliant solution
|
|
|
|
[source,javascript]
|
|
----
|
|
const expect = require("chai").expect;
|
|
const { AssertionError } = require('chai');
|
|
const fs = require("fs");
|
|
|
|
describe("exceptions are tested properly", function() {
|
|
const funcThrows = function () { throw new TypeError('What is this type?'); };
|
|
const funcNoThrow = function () { /*noop*/ };
|
|
|
|
it("forgot to pass the error to 'done()'", function(done) {
|
|
fs.readFile("/etc/zshrc", 'utf8', function(err, data) {
|
|
try {
|
|
expect(data).to.match(/some expected string/);
|
|
} catch (e) {
|
|
expect(e).to.be.an.instanceof(AssertionError);
|
|
done();
|
|
}
|
|
});
|
|
});
|
|
|
|
it("does not 'expect' a specific exception", function() {
|
|
expect(funcThrows).to.throw(TypeError);
|
|
expect(funcNoThrow).to.not.throw(Error, /My error message/);
|
|
});
|
|
});
|
|
----
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
* When an assertion function is used:
|
|
message: 'Test precisely which exception is [not] thrown.'
|
|
|
|
* When ``++try...catch...done++`` is used:
|
|
message: 'Test if the right exception is caught, or pass it to "done()" below.'
|
|
|
|
|
|
=== Highlighting
|
|
|
|
* When an assertion function is used:
|
|
** location: the assertion function
|
|
* When ``++try...catch...done++`` is used:
|
|
** Primary location: the ``++catch (e)++`` statement
|
|
** Secondary location: the call to ``++done()++``
|
|
message: 'done()" is called without checking the exception.'
|
|
|
|
|
|
endif::env-github,rspecator-view[]
|