Reputation: 11872
Ello all, So I've been trying to write a unit test that expects a certain type of exception. I had a function that threw that exception but, I still got a failing test. To troubleshoot, I've gone as far as just trying to throw the same exception and still get a fail. I can make it pass with comparing the message but, that seems like a terrible idea.
How should I be handling testing for a matching custom exception?
export class EventEntity {
comments : Array<string> = new Array<string>();
constructor() {}
public addComment(comment : string) {
this.comments.push(comment);
}
public getCommentCount() : number {
return this.comments.length;
}
public getCommentByOrder(commentNumber : number) : string {
console.log(`getCommentByOrder with arg:${commentNumber}`);
let offset = 1;
try {
let result = this.comments[commentNumber - offset];
return result;
} catch (err){
console.log(`getCommentByOrder:Error: ${err.toString()}`);
console.log(`err: with arg:${commentNumber}`);
if(err instanceof RangeError){
throw new CommentNotFoundException();
}
throw err;
}
}
}
export class CommentNotFoundException extends Error {
constructor(m?:string)
{
let message : string = m?m:"Comment number not found in event's comments.";
super(message);
Object.setPrototypeOf(this, CommentNotFoundException.prototype);
}
}
@test shouldThrowIfCommentNumberIsGreaterThanTotalNumberOfComments() {
let testEvent = new EventEntity();
let expectedException = new CommentNotFoundException();
//expect(testEvent.getCommentByOrder(5)).to.throw(expectedException);
expect(()=> {
throw new CommentNotFoundException();
}).to.throw(new CommentNotFoundException());
}
Okay, I revised. This works as expected. The exception wasn't being picked up in the form:
expect(testEvent.getCommentByOrder(5)).to.throw(CommentNotFoundException);
but this does:
expect(()=>{
testEvent.getCommentByOrder(5);
}).to.throw(CommentNotFoundException);
Here is the listing with updated code:
public getCommentByOrder(commentNumber : number) : string {
let offset = 1;
let result = this.comments[commentNumber - offset];
if (!result) {
throw new CommentNotFoundException();
} else {
return result;
}
}
@test shouldThrowIfCommentNumberIsGreaterThanTotalNumberOfComments() {
let testEvent = new EventEntity();
expect(()=>{
testEvent.getCommentByOrder(5);
}).to.throw(CommentNotFoundException);
}
That's a win, Thanks!
Upvotes: 2
Views: 2034
Reputation: 151401
You are passing an error instance to the .throw(...)
method. You need to pass a constructor instead. And what you pass to expect
must be a function that expect
will call. Your commented out line should be edited to:
expect(() => testEvent.getCommentByOrder(5)).to.throw(CommentNotFoundException);
You can pass an instance to the method but then the assertion will pass if and only if the instance raised by the function being tested and the instance you pass to .throw(...)
satisfy a comparison with ===
. In other words, the two values must be the exact same JS object. When testing real code (rather than trivial examples), it is almost never the case that you can get the error instance before the error is raised so passing an instance is something you normally cannot do.
Upvotes: 4