558

我正在尝试为Jasmine 测试框架编写一个预期错误的测试。目前我正在使用来自 GitHub 的 Jasmine Node.js 集成

在我的 Node.js 模块中,我有以下代码:

throw new Error("Parsing is not possible");

现在我尝试编写一个预期此错误的测试:

describe('my suite...', function() {
    [..]
    it('should not parse foo', function() {
    [..]
        expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
    });
});

我也尝试Error()了其他一些变体,但无法弄清楚如何使其工作。

4

10 回答 10

898

尝试使用匿名函数:

expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));

您应该将一个函数传递给expect(...)调用。您的错误代码:

// incorrect:
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));

正在尝试实际调用 parser.parse(raw)以尝试将结果传递给expect(...),

于 2010-11-10T13:13:50.637 回答
82

您正在使用:

expect(fn).toThrow(e)

但是如果你看一下函数注释(预计是字符串):

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) {

我想你可能应该这样写(使用 lambda - 匿名函数):

expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");

这在以下示例中得到证实:

expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");

Douglas Crockford强烈推荐这种方法,而不是使用“throw new Error()”(原型设计方式):

throw {
   name: "Error",
   message: "Parsing is not possible"
}
于 2010-11-10T13:06:22.480 回答
29

如前所述,需要传递一个函数,toThrow因为它是您在测试中描述的函数:“我希望这个函数抛出 x”

expect(() => parser.parse(raw))
  .toThrow(new Error('Parsing is not possible'));

如果使用Jasmine-Matchers,您也可以在适合情况时使用以下其中一种;

// I just want to know that an error was
// thrown and nothing more about it
expect(() => parser.parse(raw))
  .toThrowAnyError();

或者

// I just want to know that an error of 
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
  .toThrowErrorOfType(TypeError);
于 2017-01-24T08:51:22.027 回答
25

比创建一个唯一目的是包装另一个匿名函数的更优雅的解决方案是使用ES5bind函数。bind函数创建一个新函数,在调用该函数时,其关键字this设置为提供的值,并且在调用新函数时在任何提供的参数之前具有给定的参数序列。

代替:

expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");

考虑:

expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");

绑定语法允许您测试具有不同值的函数,this并且在我看来使测试更具可读性。也可以看看:

Jasmine 的 toThrow 匹配器是否需要将参数包装在匿名函数中?

于 2015-02-05T17:30:55.217 回答
24

我将 Jasmine 的 toThrow 匹配器替换为以下内容,它允许您匹配异常的 name 属性或其 message 属性。对我来说,这使测试更容易编写并且不那么脆弱,因为我可以执行以下操作:

throw {
   name: "NoActionProvided",
   message: "Please specify an 'action' property when configuring the action map."
}

然后使用以下内容进行测试:

expect (function () {
   .. do something
}).toThrow ("NoActionProvided");

这让我稍后可以在不中断测试的情况下调整异常消息,重要的是它抛出了预期的异常类型。

这是 toThrow 的替代品,它允许这样做:

jasmine.Matchers.prototype.toThrow = function(expected) {
  var result = false;
  var exception;
  if (typeof this.actual != 'function') {
    throw new Error('Actual is not a function');
  }
  try {
    this.actual();
  } catch (e) {
    exception = e;
  }
  if (exception) {
      result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected) || this.env.equals_(exception.name, expected));
  }

  var not = this.isNot ? "not " : "";

  this.message = function() {
    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
      return ["Expected function " + not + "to throw", expected ? expected.name || expected.message || expected : " an exception", ", but it threw", exception.name || exception.message || exception].join(' ');
    } else {
      return "Expected function to throw an exception.";
    }
  };

  return result;
};
于 2011-07-28T10:15:26.597 回答
12

我知道那是更多的代码,但你也可以这样做:

try
    Do something
    @fail Error("should send a Exception")
catch e
    expect(e.name).toBe "BLA_ERROR"
    expect(e.message).toBe 'Message'
于 2014-02-19T03:16:36.407 回答
6

对于CoffeeScript爱好者:

expect( => someMethodCall(arg1, arg2)).toThrow()
于 2014-02-15T17:41:05.950 回答
6

在我的例子中,抛出错误的函数是async,所以我遵循了这个

await expectAsync(asyncFunction()).toBeRejected();
await expectAsync(asyncFunction()).toBeRejectedWithError(...);
于 2020-07-23T17:40:13.250 回答
3

对我来说,发布的解决方案不起作用,它一直抛出这个错误:

错误:预期函数会引发异常。

后来我意识到我期望抛出错误的函数是一个异步函数,并且期望 promise 被拒绝然后抛出错误,这就是我在代码中所做的:

throw new Error('REQUEST ID NOT FOUND');

这就是我在测试中所做的,它奏效了:

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');
        });
}));
于 2018-02-15T11:09:45.707 回答
1
it('it should fail', async () => {
    expect.assertions(1);

    try {
        await testInstance.doSomething();
    }
    catch (ex) {
        expect(ex).toBeInstanceOf(MyCustomError);
    }
});
于 2021-08-10T19:30:23.850 回答