我怎样才能编写一个需要“错误”的测试?被扔进茉莉花里?

发布于 2024-10-01 04:52:00 字数 617 浏览 7 评论 0原文

我正在尝试为 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() 和其他一些变体,只是不知道如何让它发挥作用。

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.js 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

谁把谁当真 2024-10-08 04:52:00

尝试使用匿名函数:

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

或者使用 lambda:

expect( () => 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(...) ,

Try using an anonymous function instead:

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

Or using a lambda:

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

you should be passing a function into the expect(...) call. Your incorrect code:

// 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(...),

未央 2024-10-08 04:52:00

您正在使用:

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

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"
}
番薯 2024-10-08 04:52:00

如前所述,需要将函数传递给 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);

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);
倚栏听风 2024-10-08 04:52:00

比创建匿名函数(其唯一目的是包装另一个函数)更优雅的解决方案是使用 ES5 的 绑定 函数。 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");

bind 语法允许您使用不同的 this 值测试函数,在我看来,使测试更具可读性。另请参阅:

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

A more elegant solution than creating an anonymous function whose 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:

Does Jasmine's toThrow matcher require the argument to be wrapped in an anonymous function?

十秒萌定你 2024-10-08 04:52:00

我用以下内容替换 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;
};

I replace Jasmine's toThrow matcher with the following, which lets you match on the exception's name property or its message property. For me this makes tests easier to write and less brittle, as I can do the following:

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

and then test with the following:

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

This lets me tweak the exception message later without breaking tests, when the important thing is that it threw the expected type of exception.

This is the replacement for toThrow that allows this:

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;
};
轮廓§ 2024-10-08 04:52:00

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

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

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'
歌枕肩 2024-10-08 04:52:00

就我而言,抛出错误的函数是异步的,所以我遵循了这个

await expectAsync(asyncFunction()).toBeRejected();
await expectAsync(asyncFunction()).toBeRejectedWithError(...);

In my case, the function throwing an error was async, so I followed this:

await expectAsync(asyncFunction()).toBeRejected();
await expectAsync(asyncFunction()).toBeRejectedWithError(...);
同展鸳鸯锦 2024-10-08 04:52:00

对于 CoffeeScript 爱好者:

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

For CoffeeScript lovers:

expect( => someMethodCall(arg1, arg2)).toThrow()
云归处 2024-10-08 04:52:00
it('it should fail', async () => {
    expect.assertions(1);

    try {
        await testInstance.doSomething();
    }
    catch (ex) {
        expect(ex).toBeInstanceOf(MyCustomError);
    }
});
it('it should fail', async () => {
    expect.assertions(1);

    try {
        await testInstance.doSomething();
    }
    catch (ex) {
        expect(ex).toBeInstanceOf(MyCustomError);
    }
});
紫﹏色ふ单纯 2024-10-08 04:52:00

对我来说,发布的解决方案不起作用,并且不断抛出此错误:

错误:预期函数会抛出异常。

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

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

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 the promise to be rejected and then throw an error and that's what I was doing in my code:

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

And that’s 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');
        });
}));
睡美人的小仙女 2024-10-08 04:52:00

当我尝试检查异步函数是否抛出异常时,我遇到了类似的问题(以及 Stackoverflow 上的这个问题),并发现第一个答案在我创建以下辅助函数(下面是 TypeScript,删除类型)之后效果很好将为您提供纯 JavaScript):


export function toPromise(funcOrPromise: ()=>Promise| Promise): Promise{
  let promise = funcOrPromise instanceOf Promise ? funcOrPromise : funcOrPromise();
  return new Promise((resolve, reject) => promise.then( r=>resolve(r)).catch(e=>reject(e)));
}

用作此:

asyncExpect(toPromise(asyncFunc)).toBeRejectedWithError(/error text/);

asyncExpect(toPromise(asyncFunc())).toBeRejectedWithError(/error text/);

I ran into similar problem (and this question on Stackoverflow) when was trying to check that async function throws, and found that first answer works great after I create a following helper function (below is TypeScript, removing types will give you plain JavaScript):


export function toPromise(funcOrPromise: ()=>Promise| Promise): Promise{
  let promise = funcOrPromise instanceOf Promise ? funcOrPromise : funcOrPromise();
  return new Promise((resolve, reject) => promise.then( r=>resolve(r)).catch(e=>reject(e)));
}

To be used as this:

asyncExpect(toPromise(asyncFunc)).toBeRejectedWithError(/error text/);

or

asyncExpect(toPromise(asyncFunc())).toBeRejectedWithError(/error text/);
吃不饱 2024-10-08 04:52:00

受到 Juan Rada 答案的启发,这是一种“穷人”的方法,仅使用 expect(a).toBe(b)

it('Throws an error when doing xyz', function() {
  let caughtError = '';
  try {
    xyz();
  } catch (e) {
    caughtError = e.message;
  }
  expect( caughtError ).toBe( 'Parsing is not possible' );
});

Inspired by Juan Rada's answer, here is a "poor man's" approach, using only expect(a).toBe(b):

it('Throws an error when doing xyz', function() {
  let caughtError = '';
  try {
    xyz();
  } catch (e) {
    caughtError = e.message;
  }
  expect( caughtError ).toBe( 'Parsing is not possible' );
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文