节点:用一个callback参数模拟一个函数

我正在尝试编写一个函数读取一个jsonfile到一个对象的unit testing。 我读了文件

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

对于我的unit testing,我想嘲笑这个函数,而不是实际读取文件,它只会返回一个固定的json块并传递给callback函数。

我遇到的麻烦是如何嘲笑这个function。 我见过sinon ,它支持模拟函数,但我找不到任何描述如何为我正在嘲笑的函数实际定义自定义行为。 Sinon看起来像允许我定义我想要的函数返回,我期望它被调用的频率等等,但是实际上并没有定义一个模拟函数。

基本上,我想要这样的东西:

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

我怎么和sinon做这个?

但是实际上,为什么不用一个具有相同定义的函数replacereadFile(这样就不会使用它来破坏代码)。 只是返回你的模拟数据。

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

那样容易。

否则,如果您不想处理定义,则可以使用代理:

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

这在testing中并不简单,因为它涉及callbacks 。 你需要testing一下你传递给readFile的callback是否被正确的参数调用,在这种情况下是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(); 

如果你想把这个抽象成一个函数,那么它可以是这样的:

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

我正在寻找的函数是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 

它看起来不像是我想做的mock