Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sinon.js, only stub a method once?

I am wondering is there is a possibility in sinon.js to stub a method only once?

For example:

sinon.stub(module, 'randomFunction', 'returnValue/function');

In my test this module.randomFunction will be called multiple times in the same test, but I only want the stub to trigger once and then restore it so the function goes back to its normal behaviour.

Simulation of the real code:

myModule.putItem(item, function (err, data) {
  if (err) {
    // do stuff
    return callback();
  } else {
    // do other stuff
    return callback(null, data);
  }
});

The first time I want to trigger the error, the other times I just want it to continue the real flow.

Is this possible in sinon?

Kind regards,

Jimmy

Edit: I posted a solution I found for my problem based on the answer of @Grimurd

like image 870
jruts Avatar asked May 20 '16 09:05

jruts


People also ask

How do you stub a function with Sinon?

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. For example, the below code stubs out axios.

How do I reset my Sinon stub?

var stub = sinon. The original function can be restored by calling object. method. restore(); (or stub. restore(); ).

How do you mock a method 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.


2 Answers

Yes it is possible. Assuming you are using mocha as your testing framework.

describe('some tests', function() {    
    afterEach(function() {
        sinon.restore();
    })

    it('is a test with a stub', function() {
        // This gets restored after each test.
        sinon.stub(module, 'randomFunction', 'returnValue/function');
    })
})

Check out the sinon sandbox api for more info.

UPDATE

To answer your actual problem,

describe('some tests', function() {
    afterEach(function() {
        sinon.restore();
    })

    it('is a test with a stub', function() {
        // This gets restored after each test.
        sinon.stub(module, 'randomFunction')
            .onFirstCall().returns('foo')
            .onSecondCall().returns('bar')
            .onThirdCall().returns('foobar');
    })
})

Documented on http://sinonjs.org/docs/ search for stub.onCall(n)

Update 2: Since v5 sinon now creates a sandbox by default so it's no longer necessary to explicitly create a sandbox. See the migration guide from v4 to v5 for more information

like image 196
grimurd Avatar answered Nov 26 '22 21:11

grimurd


Solution:

sandbox.stub(module, 'putItem')
  .onFirstCall().yields('ERROR')
  .onSecondCall().yields(null, item)

Based on the answer of @grimurd I managed to get it working with 'yields'. Yields triggers the first callback function it finds in the original method signature.

So on the first call I basically say callback('error') and on the second call I say callback(null, item).

Somehow I do wonder if callback would have been a better method name than yields ;)

Thanks for the answers!

like image 21
jruts Avatar answered Nov 26 '22 21:11

jruts