J'ai un cours qui refuse une promesse:
Sync.prototype.doCall = function(verb, method, data) {
var self = this;
self.client = P.promisifyAll(new Client());
var res = this.queue.then(function() {
return self.client.callAsync(verb, method, data)
.then(function(res) {
return;
})
.catch(function(err) {
// This is what gets called in my test
return P.reject('Boo');
});
});
this.queue = res.delay(this.options.throttle * 1000);
return res;
};
Sync.prototype.sendNote = function(data) {
var self = this;
return self.doCall('POST', '/Invoice', {
Invoice: data
}).then(function(res) {
return data;
});
};
Dans mon test:
return expect(s.sendNote(data)).to.eventually.be.rejectedWith('Boo');
Cependant, pendant que le test réussit, l'erreur est renvoyée vers la console.
Rejet non géré Erreur: Boo ...
Avec des erreurs non promises, j’ai utilisé bind to test pour empêcher que l’erreur ne soit renvoyée tant que Chai n’a pas pu boucler et tester:
return expect(s.sendNote.bind(s, data)).to.eventually.be.rejectedWith('Boo');
Cependant, cela ne fonctionne pas avec cela et renvoie:
TypeError: [Function] is not a thenable.
Quelle est la bonne façon de tester cela?
Vous recevez l'erreur car sendNote est rejeté et vous ne la détectez pas.
Essayer:
var callPromise = self.doCall('POST', '/Invoice', {
Invoice: data
}).then(function(res) {
return data;
});
callPromise.catch(function(reason) {
console.info('sendNote failed with reason:', reason);
});
return callPromise;
Il semblerait que vous deviez également déplacer votre capture existante d'un bloc vers l'autre:
var res = this.queue.then(function() {
return self.client.callAsync(verb, method, data)
.then(function(res) {
return;
});
}).catch(function(err) {
// This is what gets called in my test
return P.reject('Boo');
});
(Avertissement: C'est une bonne question, même pour les personnes qui n'utilisent pas Bluebird. J'ai posté une réponse similaire ici ; cette réponse fonctionnera pour les personnes qui n'utilisent pas Bluebird.)
Voici comment vous pouvez utiliser chai-as-promise pour tester les cas resolve
et reject
avec une promesse:
var chai = require('chai');
var expect = chai.expect;
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
...
it('resolves as promised', function() {
return expect(Promise.resolve('woof')).to.eventually.equal('woof');
});
it('rejects as promised', function() {
return expect(Promise.reject('caw')).to.be.rejectedWith('caw');
});
Vous pouvez accomplir la même chose sans chai comme promis, comme ceci:
it('resolves as promised', function() {
return Promise.resolve("woof")
.then(function(m) { expect(m).to.equal('woof'); })
.catch(function(e) { throw e }) // use error thrown by test suite
;
});
it('rejects as promised', function() {
return Promise.reject("caw")
.then(function(m) { throw new Error('was not supposed to succeed'); })
.catch(function(m) { expect(m).to.equal('caw'); })
;
});
Personnellement, j'utilise cet idiome:
it('rejects as promised', function() {
return Promise.reject("caw")
.then(
(m) => { assert.fail('was not supposed to succeed'); }
(m) => { /* some extra tests here */ }
);
});
C'est l'un des rares cas où then(onFulfilled, onRejected)
(2 arguments) est légitime à utiliser.
Si vous enchaînez .then(reject).catch(onRejected)
comme suggéré dans d'autres réponses, vous finissez par entrer dans le gestionnaire catch
à chaque fois puisqu'il capturera également le rejet produit par le gestionnaire précédent then
- ce qui pourrait provoquer des tests à répétition si vous n'êtes pas assez prudent pour vérifier cette éventualité.