Javascript sinon存根不替换函数。

Javascript sinon存根不替换函数。,javascript,node.js,testing,mocha.js,sinon,Javascript,Node.js,Testing,Mocha.js,Sinon,我尝试了一个虚拟模块并将其存根,但不起作用 app.js function foo() { return run_func() } function run_func() { return '1' } exports._test = {foo: foo, run_func: run_func} test.js app = require("./app.js")._test describe('test', function(){ it('test', function(

我尝试了一个虚拟模块并将其存根,但不起作用

app.js

function foo()
{
    return run_func()
}
function run_func()
{
    return '1'
}
exports._test = {foo: foo, run_func: run_func}
test.js

app = require("./app.js")._test
describe('test', function(){
    it('test', function(){

        var test_stub = sinon.stub(app, 'run_func').callsFake(
          function(){
            return '0'
        })
        test_stub.restore()

        var res = app.foo()
        assert.equal('0', res)
    })
})
我尝试了以下建议:


但还是一样。它不会取代该函数。

这里有几个问题。首先,您在创建存根后立即调用
test\u stub.restore()
,这会使存根替换为原始函数,从而有效地完全撤消存根

restore
用于在测试完成后清除假方法。因此,您确实想调用它,但应该在每次调用后
调用它。

你的第二个问题有点微妙。Sinon的工作原理是覆盖对对象上函数的引用,使其指向其他对象(在本例中为存根)。它不能在其他上下文中替换对同一函数的引用

当您调用
sinon.stub(应用程序'run_func')
时,有点像这样:

app.run_func = sinon.stub()
。。。除了前者存储app.run_func的原始值和名称,允许您以后轻松恢复

请注意,此时,变量
app
指向使用
exports导出的同一对象。_test={foo:foo,run\u func:run\u func}
Your
foo
函数并没有通过该对象引用
run\u func
。它在
app.js
的范围内直接引用它,这是sinon无法影响的

看看下面的例子。你也会注意到我清理了一些其他东西:

app.js:

exports.foo = function() {
    return exports.run_func();
};

exports.run_func = function() {
    return '1';
};
test.js:

const app = require('./app');
const sinon = require('sinon');

describe('app', function() {
    describe('foo', function() {
        beforeEach(function() {
            sinon.stub(app, 'run_func').returns('0');
        });

        afterEach(function() {
            app.run_func.restore();
        });

        it('returns result of app.run_func', function() {
            assert.equal(app.foo(), '0');
        });
    });
});

注意
app.js中的
exports
如何引用与
test.js中的
app
完全相同的对象。这是因为节点中的模块默认导出一个空对象,您可以通过
exports
变量将其分配给它。

Thnx!我是JavaScript的新手,所以看起来是exports。_test={foo:foo,run\u func:run\u func}创建了一个新对象,其中包含原始函数对象的副本(我不知道这样说是否正确,我来自c++),我认为它引用了原始对象。我必须直接导出函数对象,而不是一个副本?从C/C++的角度来看,将javascript中的每个变量或对象属性都看作一个指针是很有帮助的。您不是将函数复制到新对象,而是为它提供引用,以便可以通过它访问函数<代码>导出
是当您
需要
模块时默认返回的对象。默认情况下,它是一个空对象,您可以将函数引用指定给它以“导出”它们。这是一个相当不错的教程:无论函数如何调用,都有办法替换它吗?@Ashokkumar不幸的是,没有。这个限制是JavaScript工作方式中固有的。在CommonJS模块中,该模块顶层的变量是模块的本地变量,不能从模块外部更改。因此,您需要通过模块外部可访问的对象来引用可替换的内容。大多数情况下,默认的导出对象是这方面的最佳候选对象。