web-dev-qa-db-ja.com

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

これは可能ですか?

19
bibs

Chai'sthrow構文を使用してみてください。例えば:

expect(Constructor).to.throw(Error);
12
Mark F

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

代わりに、shouldを使用できます throwError

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

チャイ

そして、チャイで 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()
});
30
Noah

チャイは今持っています

should.fail()およびexpect.fail()

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

11
shaunc

非同期コードでこれを行う必要がある場合は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)
  }
});

ポスターは同期コードのみを実行していることに注意してください。ただし、非同期を使用している多くの人々が質問のタイトルによってここに導かれたと思います!

9
mikemaccana

デフォルトのMochaは、node.jsからAssertを使用しています( https://nodejs.org/api/assert.html ) 。メソッドがエラーをスローするかどうかを確認するために外部ライブラリは必要ありません。

アサートにはメソッドがあります-_assert.throws_、3つのパラメーターがありますが、ここで重要なのは2つだけです。

  • 関数-ここでは関数を渡します関数呼び出しではありません
  • エラー-エラーをチェックするためのパスまたはオブジェクトコンストラクターまたは関数

メッセージパラメータが設定されていないときにエラーをスローするsendMessage(message)という関数があるとします。機能コード:

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

OK、それをテストするためには、入力をカバーする追加の関数が必要です。どうして? _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)
_

違いがわかりますか?関数を直接渡すのではなく、準備された入力で呼び出すために、関数呼び出しを無名関数の中に入れました。

2番目のパラメータについてはどうでしょう。どのようなエラーがスローされるかによって異なります。上記の例では、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')
_

2番目のパラメーターのErrorの代わりに、スローされたエラーと期待値を比較するために比較関数を使用しました。

5
Maciej Sikora

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')
  })
})
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で実行し、ソース内のどこに障害を記録するかを正確に指定できます。

通常、誰かがthrowまたはassert(false)に誘惑される可能性がありますが、これらは両方ともcatchtryに捕捉され、あなたにそうさせますキャッチしたエラーがテストで予想されるエラーであったか、それともテストが失敗したという最終決定であるかを判断するためのメタチェック。それはただの混乱です。

2
Ian MacDonald

should.js を使用している場合は、(new ErrorThrowingObject).should.throw('Option Error Text or Regular Expression here')

別のライブラリを使用したくない場合は、次のようにすることもできます。

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

このようにして、テストが終了した場合にエラーがキャッチされたことがわかります。そうしないと、タイムアウトエラーが発生します。

1
Max

ありChaithrow(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();
});
0
SandroMarques