2017-08-02 8 views
0

Je traite un code mélangeant des rappels de style nœud et des promesses Bluebird, et j'ai besoin d'écrire des tests unitaires pour cela.Invocation de rappel de rappel à la fin de la chaîne de promesses

En particulier, cache.js expose la fonction init(), qui fonctionne avec des promesses. Il est ensuite appelé par la fonction doSomething() dans un autre fichier (par exemple index.js) qui à son tour accepte un rappel qui doit être appelé à la fin de init().

pseudocode est la suivante:

// [ cache.js ] 
function init() { 
    return performInitialisation() 
    .then((result) => return result); 
} 


// [ index.js ] 
var cache = require('./cache'); 

function doSomething(callback) { 
    console.log('Enter'); 

    cache.init() 
    .then(() => { 
     console.log('Invoking callback'); 
     callback(null); 
    }) 
    .catch((err) => { 
     console.log('Invoking callback with error'); 
     callback(err); 
    }); 

    console.log('Exit'); 
} 

Un test unitaire possible pourrait être (montrer seulement code):

// [ index.test.js ] 
... 
var mockCache = sinon.mock(cache); 
... 
it('calls the callback on success', function(done) { 
    mockCache.expects('init') 
    .resolves({}); 

    var callback = sinon.spy(); 

    doSomething(callback); 
    expect(callback).to.have.been.calledOnce; 
    done(); 
}); 

Ce test passe, mais changer l'attente de not.have.been.calledOnce passe aussi, qui est faux.

En outre, les journaux de la console sont hors séquence:

Enter 
Exit 
Invoking callback 

J'ai regardé plusieurs possibilités, dont aucun SOLLICITÉS:

  • utilisant chaï-as-promirent, par exemple expect(callback).to.eventually.have.been.calledOnce;

  • refactorisation doSomething() être simplement:

    fonction doSomething (rappel) { cache.init() .asCallback (rappel); }

Quelqu'un peut me aider à comprendre ce que je fais mal et comment je peux résoudre ce problème s'il vous plaît?

Répondre

0

journaux de la console sont hors séquence

Les journaux sont dans l'ordre correct parce que votre Promise sera sens async, à tout le moins, les journaux de la console les appels internes à then & catch se déroulera sur la prochaine tique. La raison pour laquelle le test échoue est le résultat de quelques problèmes, le premier est que vous ne semblez pas avoir configuré sinon-chai correctement, ou au mieux, votre assertion calledOnce ne fonctionne pas. Juste pour confirmer, le haut de votre fichier de test doit quelque chose comme:

const chai = require("chai"); 
const sinonChai = require("sinon-chai"); 

chai.use(sinonChai); 

Si vous avez cela et il est toujours pas correctement alors de travail pourrait être utile d'ouvrir une question sur le sinon-chai lib, cependant, une solution simple est de passer à sinon assertions par exemple Deuxièmement, lorsque vous corrigez ce problème, vous constaterez probablement que le test échouera maintenant ... à chaque fois. Raison d'être que vous avez le même problème dans votre test que vous avez avec votre journalisation - votre affirmation avant que la promesse interne a eu une chance de résoudre.Manière la plus simple de fixer est d'utiliser réellement votre done gestionnaire de Mocha que votre affirmation

mockCache.expects('init').resolves({}); 
doSomething(() => done()); 

En d'autres termes, si done get on appelle alors vous savez que le rappel a été appelé :)

+0

Merci pour votre réponse. Si je fais 'doSomething (() => done()), alors je ne serai pas en mesure de tester la condition d'erreur, non? Je veux dire que je ne verrai pas si le callback est invoqué avec l'argument error. – rippeltippel

+0

@rippeltippel votre gestion du callback, donc le fait même que 'done' est appelé et que le test passe _is_ votre vérification. Si, pour une raison quelconque, 'callback' n'est pas appelé, votre test expirera. – James

+0

Ca a du sens, merci. – rippeltippel

0

Après James 'commentaire I revisité mes tests comme ceci:

it('calls the callback on success', function(done) { 
    mockCache.expects('init') 
    .resolves({}); 

    doSomething(done); 
}); 

it('calls the callback on error', function(done) { 
    mockCache.expects('init') 
    .rejects('Error'); 

    doSomething((err) => { 
    if (err === 'Error') { 
     done(); 
    } else { 
     done(err); 
    } 
    }); 
});