20

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:

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?

4

9 回答 9

30

应该.js

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

或者你可以使用应该throwError

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

和 chai 一起使用throw api

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()
});
于 2013-02-15T08:43:04.873 回答
14

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

expect(Constructor).to.throw(Error);
于 2013-02-14T16:45:40.463 回答
13

柴现在有

should.fail()expect.fail()

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

于 2015-03-22T19:28:45.333 回答
12

如果您需要使用异步代码执行此操作,请在 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)
  }
});

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

于 2017-07-06T11:30:27.393 回答
9

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

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

  • function - 这里传递函数,而不是函数调用
  • 错误 - 这里传递或对象构造函数或函数用于检查错误

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

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

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

所以而不是

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

您需要创建匿名函数:

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

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

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

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

现在测试调用

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

而不是Error在第二个参数中,我使用了比较函数来比较抛出的错误和期望。

于 2017-10-23T12:18:17.703 回答
4

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')
  })
})
于 2018-03-13T20:35:33.647 回答
3

如果您不想将大量源代码包装到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();
  }
}

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

通常,有人可能会尝试使用throwor ,assert(false)但这些都会被确定您的测试失败。那只是一团糟。catchtry

于 2018-12-14T19:53:56.010 回答
2

如果您使用的是should.js,您可以这样做(new ErrorThrowingObject).should.throw('Option Error Text or Regular Expression here')

如果您不想使用单独的库,也可以执行以下操作:

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

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

于 2013-02-14T16:53:25.023 回答
0

throw(ES2016)

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

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

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

这不起作用

it('Should fail if ...', done => {
    let ret = MyModule.myFunction(myArg);
    expect(ret).to.throw();
    done();
});
于 2017-11-04T13:00:54.047 回答