I'm trying to write a test for the Jasmine Test Framework which expects an error. At the moment I'm using a Jasmine Node.js integration from GitHub.
In my Node module I have the following code:
throw new Error("Parsing is not possible");
Now I try to write a test which expects this error:
describe('my suite...', function() {
[..]
it('should not parse foo', function() {
[..]
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
});
});
I tried also Error()
and some other variants and just can't figure out how to make it work.
转载于:https://stackoverflow.com/questions/4144686/how-to-write-a-test-which-expects-an-error-to-be-thrown-in-jasmine
you should be passing a function into the expect(...)
call. The code you have here:
// incorrect:
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
is trying to actually call parser.parse(raw)
in an attempt to pass the result into expect(...)
,
Try using an anonymous function instead:
expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));
You are using:
expect(fn).toThrow(e)
But if you'll have a look on the function comment (expected is string):
294 /**
295 * Matcher that checks that the expected exception was thrown by the actual.
296 *
297 * @param {String} expected
298 */
299 jasmine.Matchers.prototype.toThrow = function(expected) {
I suppose you should probably write it like this (using lambda - anonymous function):
expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");
This is confirmed in the following example:
expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");
Douglas Crockford strongly recommends this approach, instead of using "throw new Error()" (prototyping way):
throw {
name: "Error",
message: "Parsing is not possible"
}
For coffeescript lovers
expect( => someMethodCall(arg1, arg2)).toThrow()
I know that is more code but you can also do:
try
do something
@fail Error("should send a Exception")
catch e
expect(e.name).toBe "BLA_ERROR"
expect(e.message).toBe 'Message'
A more elegant solution than creating an anonymous function who's sole purpose is to wrap another, is to use es5's bind
function. The bind function creates a new function that, when called, has its this
keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
Instead of:
expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");
Consider:
expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");
The bind syntax allows you to test functions with different this
values, and in my opinion makes the test more readable. See also: https://stackoverflow.com/a/13233194/1248889
As mentioned previously, a function needs to be passed to toThrow
as it is the function you're describing in your test: "I expect this function to throw x"
expect(() => parser.parse(raw))
.toThrow(new Error('Parsing is not possible'));
If using Jasmine-Matchers you can also use one of the following when they suit the situation;
// I just want to know that an error was
// thrown and nothing more about it
expect(() => parser.parse(raw))
.toThrowAnyError();
or
// I just want to know that an error of
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
.toThrowErrorOfType(TypeError);
For anyone who still might be facing this issue, for me the posted solution didn't work and it kept on throwing this error: Error: Expected function to throw an exception.
I later realised that the function which I was expecting to throw an error was an async function and was expecting promise to be rejected and then throw error and that's what I was doing in my code:
throw new Error('REQUEST ID NOT FOUND');
and thats what I did in my test and it worked:
it('Test should throw error if request not found', willResolve(() => {
const promise = service.getRequestStatus('request-id');
return expectToReject(promise).then((err) => {
expect(err.message).toEqual('REQUEST NOT FOUND');
});
}));