我可以使用 sinon 监视外部模块函数中的函数调用吗?

Ger*_*erd 1 node.js sinon

我有一个模块:

let xmlParser = require('./myTools').xmlParser;

function extractDataAndWrite(xmldata) {
    let doc = xmlParser(xmldata);
    ...
}

module.exports = {
    extractDataAndWrite,
};
Run Code Online (Sandbox Code Playgroud)

xmlParser现在我想测试in的调用extractDataAndWrite

var extractDataAndWrite = require('../services/importData.js').extractDataAndWrite;
var mytools = require('./myTools');

var sinon = require('sinon');

describe('Test extractDataAndWrite', function() {
    it('call xmlParser', function(done) {
        var xmlParserSpy = sinon.spy(mytools, 'xmlParser');

        extractDataAndWrite("someXML");

        console.log('xmlParserSpy: ' + xmlParserSpy.callCount);
        done();
    });
});
Run Code Online (Sandbox Code Playgroud)

我期望得到xmlParserSpy.callCount == 1但它是0!我的间谍无法工作,我必须改变什么?

oli*_*ren 5

问题是,当您spy在函数上创建 on 时,您正在用新函数替换该函数引用。这意味着引用旧函数的人将不会使用新函数。在您的情况下,事情不起作用,因为您自己的模块已经引用了旧函数引用后,您将导出的函数引用包装在 'mytools

您需要研究的通用技术称为依赖注入和链接接缝。Sinon 文档对后者有一个很好的教程,使用proxyquire.

本质上你会得到这个:

const proxyquire = require('proxyquire');
const toolsStub = createToolsStub();
const importData = proxyquire('../services/importData.js', {
    './myTools': toolsStub
});

function createToolsStub(){
    return { xmlParser : sinon.stub().returns({mydoc:{foo:'bar'}};
}
Run Code Online (Sandbox Code Playgroud)

然后稍后在您的测试中您可以检查xmlParser呼叫

assert(toolsStub.xmlParser.calledWith('arg1', 'arg2');
Run Code Online (Sandbox Code Playgroud)