柴:是否预期错误取决于参数

Chai: expecting an error or not depending on a parameter

本文关键字:错误 取决于 参数 是否      更新时间:2023-09-26

我一直在尝试做一个函数的文本,该函数处理错误的方式是,如果它是一个有效的错误,它就会被抛出,但如果不是,那么什么都不会抛出。问题是我在使用时似乎无法设置参数:

expect(handleError).to.throw(Error);

理想的情况是使用:

expect(handleError(validError)).to.throw(Error);

有什么方法可以实现此功能吗?

函数代码:

function handleError (err) {
    if (err !== true) {
        switch (err) {
            case xxx:
            ...
        }
        throw "stop js execution";
    else {}
}

和测试代码(未按预期工作):

it("should stop Javascript execution if the parameter isnt '"true'"", function() {
    expect(handleError).to.be.a("function");
    expect(handleError(true)).to.not.throw(Error);
    expect(handleError("anything else")).to.throw(Error);
});

问题是您正在调用handleError,然后将结果传递给预期。如果 handleError 抛出,那么期望甚至永远不会被调用。

您需要将调用 handleError 推迟到调用 expect,以便 expect 可以看到调用函数时会发生什么。幸运的是,这就是期望想要的:

expect(function () { handleError(true); }).to.not.throw();
expect(function () { handleError("anything else") }).to.throw("stop js execution");

如果你阅读了 throw 的文档,你会看到相关的期望应该被传递给一个函数。

我今天遇到了同样的问题,并选择了这里没有提到的另一个解决方案:使用bind()的部分函数应用程序:

expect(handleError.bind(null, true)).to.not.throw();
expect(handleError.bind(null, "anything else")).to.throw("stop js execution");

这样做的好处是简洁,使用普通的旧JavaScript,不需要额外的函数,如果你的函数依赖于它,你甚至可以提供this的值。

按照David Norman的建议,将函数调用包装在Lambda中无疑是解决此问题的好方法。

但是,如果您正在寻找更具可读性的解决方案,则可以将其添加到测试实用程序中。此函数使用方法 withArgs 将您的函数包装在一个对象中,这允许您以更易读的方式编写相同的语句。理想情况下,这将内置在柴中。

var calling = function(func) {
  return {
    withArgs: function(/* arg1, arg2, ... */) {
      var args = Array.prototype.slice.call(arguments);
      return function() {
        func.apply(null, args);
      };
    }
  };
};

然后像这样使用它:

expect(calling(handleError).withArgs(true)).to.not.throw();        
expect(calling(handleError).withArgs("anything else")).to.throw("stop js execution");

它读起来像英语!

我将 ES2015 与 babel stage-2 预设一起使用,如果您这样做,您也可以使用它。

我采用了@StephenM347解决方案并对其进行了一点修改,使其更短,恕我直言:

let expectCalling = func => ({ withArgs: (...args) => expect(() => func(...args)) });

用法:

expectCalling(handleError).withArgs(true).to.not.throw();        
expectCalling(handleError).withArgs("anything else").to.throw("stop js execution");

注意:如果您希望相同的用法(并坚持按原样使用expect()):

    let calling = func => ({ withArgs: (...args) => () => func(...args) });