首页 文章

如何编写一个期望在Jasmine中抛出Error的测试?

提问于
浏览
406

我正在尝试为Jasmine Test Framework编写测试,期望出现错误 . 目前我正在使用Jasmine Node.js integration from GitHub .

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

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() 和其他一些变种,只是无法弄清楚如何让它工作 .

8 回答

  • 20

    你应该将一个函数传递给 expect(...) 调用 . 你在这里的代码:

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

    试图将结果传递给 expect(...) 实际上是 call parser.parse(raw)

    请尝试使用匿名函数:

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

    您正在使用:

    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"
    }
    
  • 0

    我用以下代码替换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;
    };
    
  • 60

    一个更优雅的解决方案莫过于创建一个匿名函数's sole purpose is to wrap another, is to use es5' s bind函数 . 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 值测试函数,并且在我看来,使测试更具可读性 . 另见:https://stackoverflow.com/a/13233194/1248889

  • 5

    如前所述,函数需要传递给 toThrow ,因为它是您在测试中描述的函数:"I expect this function to throw 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);
    
  • 697

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

    try
       do something
       @fail Error("should send a Exception")
     catch e
       expect(e.name).toBe "BLA_ERROR"
       expect(e.message).toBe 'Message'
    
  • 22

    对于coffeescript爱好者

    expect( => someMethodCall(arg1, arg2)).toThrow()
    
  • 8

    对于仍然可能面临这个问题的任何人,对我来说,发布的解决方案不起作用并且它继续抛出此错误: Error: Expected function to throw an exception. 我后来意识到我期望抛出错误的函数是异步函数并且期待承诺被拒绝然后抛出错误,这就是我在我的代码中所做的事情:

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

相关问题