Chaiのexpect.to.throw
を私のnode.jsアプリのテストで動作させるのに問題があります。テストはスローされたエラーで失敗し続けますが、私がテストケースをtry and catchでラップし、捕捉されたエラーを表明すれば、うまくいきます。
expect.to.throw
は、私がやるべきだと思うようなものではないのでしょうか。
it('should throw an error if you try to get an undefined property', function (done) {
var params = { a: 'test', b: 'test', c: 'test' };
var model = new TestModel(MOCK_REQUEST, params);
// neither of these work
expect(model.get('z')).to.throw('Property does not exist in model schema.');
expect(model.get('z')).to.throw(new Error('Property does not exist in model schema.'));
// this works
try {
model.get('z');
}
catch(err) {
expect(err).to.eql(new Error('Property does not exist in model schema.'));
}
done();
});
失敗:
19 passing (25ms)
1 failing
1) Model Base should throw an error if you try to get an undefined property:
Error: Property does not exist in model schema.
関数をexpect
に渡す必要があります。このような:
expect(model.get.bind(model, 'z')).to.throw('Property does not exist in model schema.');
expect(model.get.bind(model, 'z')).to.throw(new Error('Property does not exist in model schema.'));
あなたがしているやり方では、あなたはmodel.get('z')
を呼び出した結果をexpect
に渡しています。しかし、何かがスローされたかどうかをテストするには、expect
に関数を渡す必要があります。expect
は自分自身を呼び出します。上記のbind
メソッドは、呼び出されるとthis
をmodel
の値に設定し、最初の引数をmodel.get
に設定して'z'
を呼び出す新しい関数を作成します。
bind
の詳しい説明はこちら にあります 。
この答えが を言っているように、あなたは単にこのような無名関数であなたのコードをラップすることもできます:
expect(function(){
model.get('z');
}).to.throw('Property does not exist in model schema.');
また、すでにES6/ES2015を使用している場合は、矢印機能も使用できます。基本的には通常の無名関数を使用するのと同じですが、短くなります。
expect(() => model.get('z')).to.throw('Property does not exist in model schema.');
この質問には、Chaiアサーションライブラリに言及していない質問を含め、多くの重複があります。これがまとめられた基本です。
アサーションは直ちに評価するのではなく、関数を呼び出す必要があります。
assert.throws(x.y.z);
// FAIL. x.y.z throws an exception, which immediately exits the
// enclosing block, so assert.throw() not called.
assert.throws(()=>x.y.z);
// assert.throw() is called with a function, which only throws
// when assert.throw executes the function.
assert.throws(function () { x.y.z });
// if you cannot use ES6 at work
function badReference() { x.y.z }; assert.throws(badReference);
// for the verbose
assert.throws(()=>model.get(z));
// the specific example given.
homegrownAssertThrows(model.get, z);
// a style common in Python, but not in JavaScript
任意のアサーションライブラリを使用して特定のエラーを確認できます。
assert.throws(() => x.y.z);
assert.throws(() => x.y.z, ReferenceError);
assert.throws(() => x.y.z, ReferenceError, /is not defined/);
assert.throws(() => x.y.z, /is not defined/);
assert.doesNotThrow(() => 42);
assert.throws(() => x.y.z, Error);
assert.throws(() => model.get.z, /Property does not exist in model schema./)
should.throws(() => x.y.z);
should.throws(() => x.y.z, ReferenceError);
should.throws(() => x.y.z, ReferenceError, /is not defined/);
should.throws(() => x.y.z, /is not defined/);
should.doesNotThrow(() => 42);
should.throws(() => x.y.z, Error);
should.throws(() => model.get.z, /Property does not exist in model schema./)
expect(() => x.y.z).to.throw();
expect(() => x.y.z).to.throw(ReferenceError);
expect(() => x.y.z).to.throw(ReferenceError, /is not defined/);
expect(() => x.y.z).to.throw(/is not defined/);
expect(() => 42).not.to.throw();
expect(() => x.y.z).to.throw(Error);
expect(() => model.get.z).to.throw(/Property does not exist in model schema./);
テストを「エスケープ」する例外を処理する必要があります
it('should handle escaped errors', function () {
try {
expect(() => x.y.z).not.to.throw(RangeError);
} catch (err) {
expect(err).to.be.a(ReferenceError);
}
});
これは、最初はわかりにくいかもしれません。自転車に乗るのと同じように、クリックすると永久に「クリック」されます。
doc ...;)の例
なぜならあなたはthiscontextに頼るからです
あなたはこれらのオプションの1つを使わなければなりません:
bindコンテキスト
// wrap the method or function call inside of another function
expect(function () { cat.meow(); }).to.throw(); // Function expression
expect(() => cat.meow()).to.throw(); // ES6 arrow function
// bind the context
expect(cat.meow.bind(cat)).to.throw(); // Bind
もう1つの可能な実装は、.bind()ソリューションより面倒ですが、expect()がカバーされた関数にthis
コンテキストを提供する関数を必要とするという点を明確にするのを助けるもの、あなたはcall()
を使用できます。
expect(function() {model.get.call(model, 'z');}).to.throw('...');