2017-09-27 1 views
1

J'essaie d'écrire des tests unitaires pour une fonction qui lit un fichier json dans un objet. J'ai lu le fichier avecnœud: se moquer d'une fonction avec un argument de rappel

jsonfile.readFile(filename, function (err, obj) { 
    //... 
}); 

Pour mes tests unitaires, je veux railler cette fonction de sorte que, plutôt que de lire réellement le fichier, il suffit de retourner un bloc fixe JSON et passer dans le rappel.

Ce qui me pose problème, c'est comment se moquer de la fonction. J'ai vu sinon, qui dit qu'il supporte les fonctions moqueuses, mais je ne trouve rien qui décrive comment définir un comportement personnalisé pour la fonction que je moque. Sinon ressemble à ce qui me permet de définir ce que je veux que la fonction retourne, à quelle fréquence je m'attends à ce qu'il soit appelé, etc., mais ne définisse pas réellement une fonction mockée.

Fondamentalement, je veux quelque chose comme ceci:

mock(jsonfile, 'readFile', function(filename, callback) { 
    callback(null, {attr1:"foo"}); 
}); 

Comment puis-je faire avec sinon?

Répondre

0

La fonction que je cherchais est stub.callsFake():

> Thing = { 
... meth : function() { console.log(1) } 
... } 
> Thing.meth() 
1 
> var stub = sinon.stub(Thing, 'meth') 
> stub.callsFake(function() { console.log(2) }) 
> Thing.meth() 
2 
> stub.restore() 
> Thing.meth() 
1 

Il ne ressemble pas à mock est capable de ce que je veux faire.

1

Cela n'est pas simple dans les tests car il s'agissait de callbacks. Vous devez tester si un callback que vous avez passé à readFile a été appelé avec les bons arguments, qui dans ce cas est le dummyFile.

import sinon from 'sinon' 
    import jsonfile from './jsonfile' 

    const jsonFileMock = sinon.spy(jsonfile, 'readFile'); 
    const callback = sinon.spy(); 

    jsonfile.readFile(callback); 
    jsonFileMock.callsArgWith(1, 'dummyFileName'); 

    expect(callback.calledWith('dummyFileName')).to.be.true; 
    jsonFileMock.restore(); 

Si vous voulez abstraite cela en fonction, que cela peut être quelque chose comme:

function mock(module, method, ...callbacks){ 
    const stub = sinon.stub(jsonfile, 'readFile'); 
    callbacks.forEach((callback, index) => { 
    stub.callsArgWith(index, callback); 
    }); 
} 
+1

Ce n'est pas ce que j'essaie de faire. J'essaye de simuler la fonction 'readFile' pour appeler une fonction anonyme que je définis dans mon cas de test (ce que je ferai avec de nombreuses autres fonctions dans le futur, ce n'est qu'un exemple). – ewok

1

Mais en fait, pourquoi ne vous remplacez tout simplement pas readFile par une fonction avec la même définition (afin qu'il ne casse pas le code en l'utilisant). Et renvoyez simplement vos données simulées.

jsonfile.readFile = function(filePath, callback) { 
    callback(null, { mockData: "foo" }); 
}; 

facile comme cela.

Sinon, vous pouvez utiliser un proxy si vous ne voulez pas faire face à la définition:

const jsonfile = { 
 
    readFile: function(filename, callback) { 
 
     callback(); 
 
    } 
 
}; 
 

 
// intercept every call to readFile and always return the mock data 
 
jsonfile.readFile = new Proxy(jsonfile.readFile, { 
 
    apply: function(target, thisArg, args) { 
 
     return args[1](null, { someMocking: "" }); 
 
    } 
 
}); 
 

 
// call readFile as usual 
 
jsonfile.readFile('testfile', function(err, result) { 
 
    console.log(result); 
 
});

proxies travail comme intercepteurs.

https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Proxy