Added support for throw(errorInstance).

Closes #47.
This commit is contained in:
domenic 2012-04-06 18:19:28 -04:00
parent f58f1ebb12
commit 41f645dbb8
3 changed files with 78 additions and 10 deletions

View file

@ -849,15 +849,19 @@ Assertion.prototype.keys = function(keys) {
/**
* # .throw(constructor)
*
* Assert that a function will throw a specific type of error (as determined using
* `instanceof`) and/or that the error thrown will match a RegExp or include a string.
* Assert that a function will throw a specific type of error, or specific type of error
* (as determined using `instanceof`), optionally with a RegExp or string inclusion test
* for the error's message.
*
* var fn = function () { throw new ReferenceError('This is a bad function.'); }
* var err = new ReferenceError('This is a bad function.');
* var fn = function () { throw err; }
* expect(fn).to.throw(ReferenceError);
* expect(fn).to.throw(Error);
* expect(fn).to.throw(/bad function/);
* expect(fn).to.not.throw('good function');
* expect(fn).to.throw(ReferenceError, /bad function/);
* expect(fn).to.throw(err);
* expect(fn).to.not.throw(new RangeError('Out of range.'));
*
* Please note that when a throw expectation is negated, it will check each
* parameter independently, starting with error constructor type. The appropriate way
@ -877,7 +881,8 @@ Assertion.prototype.keys = function(keys) {
Assertion.prototype.throw = function (constructor, msg) {
new Assertion(this.obj).is.a('function');
var thrown = false;
var thrown = false
, desiredError = null;
if (arguments.length === 0) {
msg = null;
@ -885,12 +890,25 @@ Assertion.prototype.throw = function (constructor, msg) {
} else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
msg = constructor;
constructor = null;
} else if (constructor && constructor instanceof Error) {
desiredError = constructor;
constructor = null;
msg = null;
}
try {
this.obj();
} catch (err) {
// first, check constructor
// first, check desired error
if (desiredError) {
this.assert(
err === desiredError
, 'expected ' + this.inspect + ' to throw ' + inspect(desiredError) + ' but ' + inspect(err) + ' was thrown'
, 'expected ' + this.inspect + ' to not throw ' + inspect(desiredError)
);
return this;
}
// if we weren't passed one, check constructor
if (constructor && 'function' === typeof constructor) {
var name = (new constructor()).name;
this.assert(
@ -919,12 +937,12 @@ Assertion.prototype.throw = function (constructor, msg) {
}
}
var name = (constructor ? constructor.name : 'an error');
var expectedThrown = (constructor ? constructor.name : desiredError ? inspect(desiredError) : 'an error');
this.assert(
thrown === true
, 'expected ' + this.inspect + ' to throw ' + name
, 'expected ' + this.inspect + ' to not throw ' + name);
, 'expected ' + this.inspect + ' to throw ' + expectedThrown
, 'expected ' + this.inspect + ' to not throw ' + expectedThrown);
return this;
};

View file

@ -424,23 +424,31 @@ suite('expect', function () {
};
PoorlyConstructedError.prototype = Object.create(Error.prototype);
var specificError = new RangeError('boo');
var goodFn = function () { 1==1; }
, badFn = function () { throw new Error('testing'); }
, refErrFn = function () { throw new ReferenceError('hello'); }
, ickyErrFn = function () { throw new PoorlyConstructedError(); };
, ickyErrFn = function () { throw new PoorlyConstructedError(); }
, specificErrFn = function () { throw specificError; };
expect(goodFn).to.not.throw();
expect(goodFn).to.not.throw(Error);
expect(goodFn).to.not.throw(specificError);
expect(badFn).to.throw();
expect(badFn).to.throw(Error);
expect(badFn).to.not.throw(ReferenceError);
expect(badFn).to.not.throw(specificError);
expect(refErrFn).to.throw();
expect(refErrFn).to.throw(ReferenceError);
expect(refErrFn).to.throw(Error);
expect(refErrFn).to.not.throw(TypeError);
expect(refErrFn).to.not.throw(specificError);
expect(ickyErrFn).to.throw();
expect(ickyErrFn).to.throw(PoorlyConstructedError);
expect(ickyErrFn).to.throw(Error);
expect(ickyErrFn).to.not.throw(specificError);
expect(specificErrFn).to.throw(specificError);
expect(badFn).to.throw(/testing/);
expect(badFn).to.not.throw(/hello/);
@ -458,6 +466,10 @@ suite('expect', function () {
expect(goodFn).to.throw(ReferenceError);
}, "expected [Function] to throw ReferenceError");
err(function(){
expect(goodFn).to.throw(specificError);
}, "expected [Function] to throw [RangeError: boo]");
err(function(){
expect(badFn).to.not.throw();
}, "expected [Function] to not throw an error");
@ -466,6 +478,10 @@ suite('expect', function () {
expect(badFn).to.throw(ReferenceError);
}, "expected [Function] to throw ReferenceError but a Error was thrown");
err(function(){
expect(badFn).to.throw(specificError);
}, "expected [Function] to throw [RangeError: boo] but [Error: testing] was thrown");
err(function(){
expect(badFn).to.not.throw(Error);
}, "expected [Function] to not throw Error");
@ -486,6 +502,14 @@ suite('expect', function () {
expect(ickyErrFn).to.throw(ReferenceError);
}, "expected [Function] to throw ReferenceError but a PoorlyConstructedError was thrown");
err(function(){
expect(specificErrFn).to.throw(new ReferenceError('eek'));
}, "expected [Function] to throw [ReferenceError: eek] but [RangeError: boo] was thrown");
err(function(){
expect(specificErrFn).to.not.throw(specificError);
}, "expected [Function] to not throw [RangeError: boo]");
err(function (){
expect(badFn).to.not.throw(/testing/);
}, "expected [Function] to throw error not matching /testing/");

View file

@ -424,23 +424,31 @@ suite('should', function() {
};
PoorlyConstructedError.prototype = Object.create(Error.prototype);
var specificError = new RangeError('boo');
var goodFn = function () { 1==1; }
, badFn = function () { throw new Error('testing'); }
, refErrFn = function () { throw new ReferenceError('hello'); }
, ickyErrFn = function () { throw new PoorlyConstructedError(); };
, ickyErrFn = function () { throw new PoorlyConstructedError(); }
, specificErrFn = function () { throw specificError; };
(goodFn).should.not.throw();
(goodFn).should.not.throw(Error);
(goodFn).should.not.throw(specificError);
(badFn).should.throw();
(badFn).should.throw(Error);
(badFn).should.not.throw(ReferenceError);
(badFn).should.not.throw(specificError);
(refErrFn).should.throw();
(refErrFn).should.throw(ReferenceError);
(refErrFn).should.throw(Error);
(refErrFn).should.not.throw(TypeError);
(refErrFn).should.not.throw(specificError);
(ickyErrFn).should.throw();
(ickyErrFn).should.throw(PoorlyConstructedError);
(ickyErrFn).should.throw(Error);
(ickyErrFn).should.not.throw(specificError);
(specificErrFn).should.throw(specificError);
(badFn).should.throw(/testing/);
(badFn).should.throw('testing');
@ -452,8 +460,10 @@ suite('should', function() {
should.throw(refErrFn, ReferenceError);
should.throw(refErrFn, Error);
should.throw(ickyErrFn, PoorlyConstructedError);
should.throw(specificErrFn, specificError);
should.not.throw(goodFn);
should.not.throw(badFn, ReferenceError);
should.not.throw(badFn, specificError);
should.throw(badFn, Error, /testing/);
should.throw(badFn, Error, 'testing');
@ -466,6 +476,10 @@ suite('should', function() {
(goodFn).should.throw(ReferenceError);
}, "expected [Function] to throw ReferenceError");
err(function(){
(goodFn).should.throw(specificError);
}, "expected [Function] to throw [RangeError: boo]");
err(function(){
(badFn).should.not.throw();
}, "expected [Function] to not throw an error");
@ -474,6 +488,10 @@ suite('should', function() {
(badFn).should.throw(ReferenceError);
}, "expected [Function] to throw ReferenceError but a Error was thrown");
err(function(){
(badFn).should.throw(specificError);
}, "expected [Function] to throw [RangeError: boo] but [Error: testing] was thrown");
err(function(){
(badFn).should.not.throw(Error);
}, "expected [Function] to not throw Error");
@ -494,6 +512,14 @@ suite('should', function() {
(ickyErrFn).should.throw(ReferenceError);
}, "expected [Function] to throw ReferenceError but a PoorlyConstructedError was thrown");
err(function(){
(specificErrFn).should.throw(new ReferenceError('eek'));
}, "expected [Function] to throw [ReferenceError: eek] but [RangeError: boo] was thrown");
err(function(){
(specificErrFn).should.not.throw(specificError);
}, "expected [Function] to not throw [RangeError: boo]");
err(function (){
(badFn).should.not.throw(/testing/);
}, "expected [Function] to throw error not matching /testing/");