测试摩卡的预期失败

时间:2013-02-14 16:15:25

标签: node.js unit-testing mocha

使用Mocha,我试图测试构造函数是否抛出错误。我无法使用expect语法执行此操作,因此我想执行以下操作:

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

这可能吗?

9 个答案:

答案 0 :(得分:30)

should.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.*/)

使用throw api

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

答案 1 :(得分:11)

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

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

答案 2 :(得分:11)

柴现在已经

should.fail()expect.fail()

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

答案 3 :(得分:9)

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

请注意,海报只是在进行同步代码,但我希望很多使用async的人都会被问题标题带到这里!

答案 4 :(得分:5)

默认情况下,Mocha使用node.js(https://nodejs.org/api/assert.html)中的断言。您不需要任何外部库来检查方法是否抛出错误。

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

  • function - here pass function, not function call
  • 错误 - 此处传递或对象构造函数或函数用于检查错误

让我们假设您有一个名为sendMessage(message)的函数,它在未设置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我使用了比较函数来比较抛出的错误和期望值。

答案 5 :(得分:3)

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

答案 6 :(得分:1)

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

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

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

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

答案 7 :(得分:1)

如果您不想将大量源包装到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中执行位于其上方的任意代码,然后精确指定要在源中记录故障的位置。

通常情况下,某人可能会倾向于使用throwassert(false),但是它们都会被catch的{​​{1}}捕获,并导致您进行一些元操作-检查以确定您捕获的错误是测试中的预期错误,还是最终确定测试失败。只是一团糟。

答案 8 :(得分:0)

Chai static void Main(string[] args) { Test1 test1 = new Test1() { abbrv = "Test1", date = new DateTime(2017, 11, 12), completed = false }; Test1 test2 = new Test1() { abbrv = "Test2", date = new DateTime(2017, 12, 17), completed = false }; Test1 test5 = new Test1() { abbrv = "Test5", date = new DateTime(2017, 12, 12), completed = false }; Test2 test3 = new Test2() { abbrv = "Test1", date = new DateTime(2017, 11, 12), completed = false, abbrevName = "AbbrvName1" }; Test2 test4 = new Test2() { abbrv = "Test2", date = new DateTime(2017, 12, 12), completed = false, abbrevName = "AbbrvName2" }; List<Test1> listTest1 = new List<Test1>(); List<Test2> listTest2 = new List<Test2>(); List<Test2> listTest3 = new List<Test2>(); listTest1.Add(test1); listTest1.Add(test2); listTest1.Add(test5); listTest2.Add(test3); listTest2.Add(test4); for (int i = 0; i < listTest1.Count; i++) { for (int a = 0; a < listTest2.Count; a++) { if (listTest1[i].abbrv == listTest2[a].abbrv && listTest1[i].date == listTest2[a].date) { if (!listTest3.Any(x => x.abbrv == listTest1[i].abbrv)) { listTest3.Add(listTest2[a]); } } else { if (listTest1[i].abbrv == listTest2[a].abbrv) { if (!listTest3.Any(x => x.abbrv == listTest1[i].abbrv && x.date != listTest1[i].date)) { listTest3.Add(new Test.Test2() { abbrv = listTest2[a].abbrv, date = listTest2[a].date, completed = true, abbrevName = listTest2[a].abbrevName }); listTest3.Add(new Test.Test2() { abbrv = listTest1[i].abbrv, date = listTest1[i].date, completed = listTest1[i].completed, abbrevName = string.Empty }); } } else if (listTest1[i].abbrv != listTest2[a].abbrv) { if(!listTest3.Any(x => x.abbrv == listTest1[i].abbrv)) { listTest3.Add(new Test.Test2() { abbrv = listTest1[i].abbrv, date = listTest1[i].date, completed = listTest1[i].completed, abbrevName = string.Empty }); } } } } } } public class Test1 { public string abbrv { get; set; } public DateTime date { get; set; } public bool completed { get; set; } } public class Test2 { public string abbrv { get; set; } public DateTime date { get; set; } public bool completed { get; set; } public string abbrevName { get; set; } } (ES2016)

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

为清楚起见...... 这工作

throw

这不起作用

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