node:使用回调参数模拟函数

时间:2017-09-27 20:04:40

标签: javascript node.js unit-testing sinon

我正在尝试为将jsonfile读入对象的函数编写单元测试。我用

读了这个文件
jsonfile.readFile(filename, function (err, obj) {
  //...
});

对于我的单元测试,我想模拟这个函数,以便它不是实际读取文件,而是简单地返回一个固定的json块并将其传递给回调。

我遇到的问题是如何模拟这个功能。我已经看过sinon,它说它支持模拟功能,但是我无法找到任何描述如何为我嘲笑的函数实际定义自定义行为的内容。 Sinon看起来它允许我定义我希望函数返回的内容,我希望它被调用的频率等等,但实际上并没有定义一个模拟函数。

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

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

我如何用sinon做到这一点?

3 个答案:

答案 0 :(得分:2)

但实际上,为什么不用具有相同定义的函数替换readFile(这样它就不会破坏使用它的代码)。并返回您的模拟数据。

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

代理作为拦截器工作。

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

答案 1 :(得分:1)

这在测试中并不简单,因为它涉及callbacks。您需要测试传递给readFile的回调是否使用正确的参数调用,在本例中是 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);
  });
}

答案 2 :(得分:0)

我正在寻找的功能是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看起来不像我想做的那样。