node.js 测试 Mocha 中的预期失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14879181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 17:10:19  来源:igfitidea点击:

Test for expected failure in Mocha

node.jsunit-testingmocha

提问by bibs

Using Mocha, I am attempting to test whether a constructor throws an error. I haven't been able to do this using the expect syntax, so I'd like to do the following:

使用 Mocha,我试图测试构造函数是否抛出错误。我无法使用期望语法来做到这一点,所以我想执行以下操作:

it('should throw exception when instantiated', function() {
  try {
    new ErrorThrowingObject();
    // Force the test to fail since error wasn't thrown
  }
  catch (error) {
   // Constructor threw Error, so test succeeded.
  }
}

Is this possible?

这可能吗?

采纳答案by Mark

You can try using Chai'sthrowconstruct. For example:

您可以尝试使用Chai 的throw构造。例如:

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

回答by Noah

should.js

应该.js

Using the should.jslibrary with should.fail

should.js库与should.fail 结合使用

var should = require('should')
it('should fail', function(done) {
  try {
      new ErrorThrowingObject();
      // Force the test to fail since error wasn't thrown
       should.fail('no error was thrown when it should have been')
  }
  catch (error) {
   // Constructor threw Error, so test succeeded.
   done();
  }
});

Alternative you can use the should throwError

或者你可以使用 should throwError

(function(){
  throw new Error('failed to baz');
}).should.throwError(/^fail.*/)

Chai

And with chai using the throwapi

并与 chai 一起使用throwapi

var expect = require('chai').expect
it('should fail', function(done) {
  function throwsWithNoArgs() {
     var args {} // optional arguments here
     new ErrorThrowingObject(args)
  }
  expect(throwsWithNoArgs).to.throw
  done()
});

回答by shaunc

Chai now has

柴现在有

should.fail()and expect.fail()

should.fail()expect.fail()

https://github.com/chaijs/chai/releases/tag/2.1.0

https://github.com/chaijs/chai/releases/tag/2.1.0

回答by mikemaccana

2017 answer if you need to do this with async code: using await and not needing any other libraries.

2017 回答是否需要使用异步代码执行此操作:使用 await并且不需要任何其他库

it('Returns a correct error response when making a broken order', async function(){
  this.timeout(5 * 1000);
  var badOrder = {}
  try {
    var result = await foo.newOrder(badOrder)
    // The line will only be hit if no error is thrown above!
    throw new Error(`Expected an error and didn't get one!`)
  } catch(err) {
    var expected = `Missing required field`
    assert.equal(err.message, expected)
  }
});

Note the poster was only doing sync code, but I expect a lot of people using async were led here by the question title!

请注意,海报只是在做同步代码,但我希望很多使用异步的人都被问题标题引导到这里!

回答by Maciej Sikora

Mocha in default is using Assertfrom node.js (https://nodejs.org/api/assert.html). You don't need any external libraries to check if a method throws an error.

Mocha 默认使用来自 node.js 的Assert( https://nodejs.org/api/assert.html)。您不需要任何外部库来检查方法是否引发错误。

Assert has a method - assert.throws, it has three parameters, but only two really matters here:

Assert 有一个方法 - assert.throws,它有三个参数,但这里只有两个真正重要:

  • function - here pass function, not function call
  • error - here pass or object constructor or function for checking the error
  • 函数 - 这里传递函数,而不是函数调用
  • 错误 - 此处传递或对象构造函数或用于检查错误的函数

Let's imagine that you have a function called sendMessage(message)which throws an error when message parameter is not set. Function code:

假设您有一个调用的函数sendMessage(message),该函数在未设置 message 参数时引发错误。功能代码:

function sendMessage(message) {
  if (!message || typeof message !== 'string') {
     throw new Error('Wrong message');
  }
  // rest of function
}

Ok, so in order to test it, you need additional function to cover input. Why? Because assert.throwsdoesn't give any opportunity to pass parameters to the function which going to be tested.

好的,为了测试它,您需要额外的功能来覆盖输入。为什么?因为assert.throws没有机会将参数传递给要测试的函数。

So instead of

所以代替

// WRONG
assert.throws(sendMessage, Error); // THIS IS WRONG! NO POSSIBILITY TO PASS ANYTHING

you need to create anonymous function:

您需要创建匿名函数:

// CORRECT
assert.throws(() => {
  sendMessage(12);  // usage of wanted function with test parameters
}, Error)

Can you see the difference? Instead of passing function directly, I have put the function call inside anonymous function, in purpose of calling it with a prepared input.

你能看到差别吗?我没有直接传递函数,而是将函数调用放在匿名函数中,目的是用准备好的输入调用它。

What about the second parameter. It depends from what kind of error should be thrown, in above example Errorobject was thrown, so I had to put there Error. In result of this action, assert.throwscompares if thrown object is object of the same type. If instead of Errorsomething different will be thrown, then this part needs to be changed. For example instead of ErrorI will throw a value of type String.

第二个参数呢。这取决于应该抛出什么样的错误,在上面的示例Error中抛出了对象,所以我不得不把Error. 在此操作的结果中,assert.throws比较抛出的对象是否为相同类型的对象。如果不是Error抛出不同的东西,那么这部分需要改变。例如,而不是ErrorI 将抛出一个类型的值String

function sendMessage(message) {
  if (!message || typeof message !== 'string') {
     throw 'Wrong message'; // change to String
  }
  // rest of function
}

Now the test call

现在测试调用

assert.throws(() => {
  sendMessage(12); // usage of wanted function with test parameters
}, (err) => err === 'Wrong message')

Instead of Errorin second parameter I have used the comparison function in order to compare thrown error with the expectation.

Error我没有使用第二个参数,而是使用比较函数来比较抛出的错误与期望值。

回答by Andre Figueiredo

MarkJ's accepted answer is the way to go and way simpler than others here. Let me show example in real world:

MarkJ 接受的答案是要走的路,而且比这里的其他人更简单。让我在现实世界中举个例子:

function fn(arg) {
  if (typeof arg !== 'string')
    throw TypeError('Must be an string')

  return { arg: arg }
}

describe('#fn', function () {
  it('empty arg throw error', function () {
    expect(function () {
      new fn()
    }).to.throw(TypeError)
  })

  it('non-string arg throw error', function () {
    expect(function () {
      new fn(2)
    }).to.throw(TypeError)
  })

  it('string arg return instance { arg: <arg> }', function () {
    expect(new fn('str').arg).to.be.equal('str')
  })
})

回答by Ian MacDonald

If you don't want to wrap a whole lot of source into the expectparameter, or if you have many arguments to pass and it just gets ugly, you can still do this with the original syntax just fine by leveraging the doneargument that is provided (but was originally ignored):

如果您不想将大量源代码包装到expect参数中,或者如果您有很多参数要传递而它变得丑陋,您仍然可以通过利用提供的done参数来使用原始语法很好地完成此操作(但最初被忽略):

it('should throw exception when instantiated', function(done: Done) {
  try {
    new ErrorThrowingObject();
    done(new Error(`Force the test to fail since error wasn't thrown`));
  }
  catch (error) {
    // Constructor threw Error, so test succeeded.
    done();
  }
}

Because you're using donehere, it allows you go execute arbitrary code above it in the try, then specify exactly where in your source you'd like to record the failure.

因为您在done此处使用,它允许您在 中执行其上方的任意代码try,然后在源中准确指定要记录失败的位置。

Normally, someone may be tempted to throwor assert(false), but these will both be caught by the catchof the try, and cause you to do some meta-checking to determine if the error you caught was the expected error from your test, or if it was the final determination that your test failed. That's just a mess.

通常情况下,有人可能试图throwassert(false),但这些都将被捕获catchtry,并引起你做一些元检查,以确定是否抓住了误差为测试中的预期错误,或者如果它是最后的确定您的测试失败。那简直是一团糟。

回答by Max

If you are using should.jsyou can do (new ErrorThrowingObject).should.throw('Option Error Text or Regular Expression here')

如果你使用should.js你可以做(new ErrorThrowingObject).should.throw('Option Error Text or Regular Expression here')

If you don't want to should a separate library, you could also do something like this:

如果你不想单独的库,你也可以这样做:

it('should do whatever', function(done) {
    try {
        ...
    } catch(error) {
        done();
    }
}

This way, you know the error is caught if the test finishes. Otherwise, you will get a timeout error.

这样,您就知道如果测试完成,就会发现错误。否则,您将收到超时错误。

回答by SandroMarques

With Chaithrow(ES2016)

throw(ES2016)

http://chaijs.com/api/bdd/#method_throw

http://chaijs.com/api/bdd/#method_throw

For clarity... This works

为了清楚起见......这有效

it('Should fail if ...', done => {
    let ret = () => {
        MyModule.myFunction(myArg);
    };
    expect(ret).to.throw();
    done();
});

This doesn't work

这不起作用

it('Should fail if ...', done => {
    let ret = MyModule.myFunction(myArg);
    expect(ret).to.throw();
    done();
});