Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sinon stub not replacing function.

I tried a dummy module and to stub it, but does not work.

the app.js

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

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

I tried the advice from: sinon stub not replacing function

But still the same. It does not replace the function.

like image 873
J.R. Avatar asked Feb 22 '18 15:02

J.R.


People also ask

How do I use stub function?

stub() substitutes the real function and returns a stub object that you can configure using methods like callsFake() . Stubs also have a callCount property that tells you how many times the stub was called. For example, the below code stubs out axios.

How do you mock a function in Sinon?

Mocks allow you to create a fake function that passes or fails depending on your needs. You can ensure it was called with certain arguments, or check how many times it was called. You must call mock() on an object.

How does Sinon stub work?

Sinon replaces the whole request module (or part of it) during the test execution, making the stub available via require('request') and then restore it after the tests are finished? require('request') will return the same (object) reference, that was created inside the "request" module, every time it's called.

What does sandbox stub do?

sandbox. Causes all stubs and mocks created from the sandbox to return promises using a specific Promise library instead of the global one when using stub. rejects or stub. resolves . Returns the stub to allow chaining.

What is a Sinon stub?

The sinon.stub () substitutes the real function and returns a stub object that you can configure using methods like callsFake () . Stubs also have a callCount property that tells you how many times the stub was called.

How to call a function from an object in Sinon?

Show activity on this post. Sinon stubs the property of the object, not the function itself. In your case you are exporting that function within an object. So in order to properly call the function from the object, you need to replace your function call with the reference to the export object like :

What are stubs in JavaScript?

As spies, stubs can be either anonymous, or wrap existing functions. When wrapping an existing function with a stub, the original function is not called. When to use stubs?

How to make a Sinon stub respond differently on consecutive calls?

As of Sinon version 1.8, you can use the onCall method to make a stub respond differently on consecutive calls. Note that in Sinon version 1.5 to version 1.7, multiple calls to the yields* and callsArg* family of methods define a sequence of behaviors for consecutive calls. As of 1.8, this functionality has been removed in favor of the onCall API.


1 Answers

You have a couple of problems here. The first is that you're calling test_stub.restore() immediately after creating the stub, which causes it to replace itself with the original function, effectively undoing the stub completely.

restore is meant for cleaning up fake methods after your test is done. So you do want to call it, but you should do so in an afterEach.

Your second problem is a little more subtle. Sinon works by overwriting a reference to a function on an object, making it point at something else (in this case, the stub). It can't replace references to the same function in other contexts.

When you call sinon.stub(app, 'run_func'), it's a bit like this:

app.run_func = sinon.stub()

... except that the former way stores the original value and name of app.run_func, allowing you to easily restore it later.

Note that at this point, the variable app points to the same object you exported with exports._test = {foo: foo, run_func: run_func} Your foo function, however, is not referencing run_func through this object. It's referencing it directly in the scope of app.js, which sinon cannot affect.

Take a look at the following example. You'll also note I cleaned up a few other things:

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

Note how exports in app.js refers to the exact same object that app does in test.js. This is because modules in node export an empty object by default, which you can assign onto by way of the exports variable.

like image 179
sripberger Avatar answered Sep 20 '22 19:09

sripberger