如何编写一个期望 Jasmine 出错的测试?

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');
                });
            }));