sinon stub by example

Mar 18, 2014 00:00 · 598 words · 3 minute read Programming JavaScript sinon

What is Stub ?

“stubs replace the real object with a test specific object that feed the desire indirect inputs into the system under test”. (xUnit test pattern)

stubs function has pre-programmed behaviour. they support all the spies functionalities as well.

When to use Stub?

stubs do not proxy the original method , they have an API for controlling the behaviour .

Use stubs when you want to

  • control the method behaviour, for instance force a method to throwing an exception to check the error handling functionalities.
  • prevent a method to get call directly to stop triggering undesired behaviour (sinon stub documentaion).

Production Code

below is the production code that suppose to give us some simple functionalities.

production codeJavaScript

var sinonStub = {
 
    callMyMethod: function (number, arg1, arg2) {
        var someValue = '';
        for (var i = 0; i < number; i++) {
            someValue = this.myMethod(arg1, arg2);
        }
        return someValue;
    },
 
    myMethod: function (arg1, arg2) {
        try {
            this.exceptionMethod();
        }
        catch (exception) {
        }
        return 'test'
    },
 
    myMethodWithCallBack: function () {
        var status;
        this.methodWithCallBack({
            onSuccess: function (arg1, arg2) {
                status = 'success' + arg1 + arg2;
            },
            onError: function () {
                status = 'failure'
            }
        });
        return status;
    },
 
    methodWithCallBack: function (callback) {
        return true;
    },
    exceptionMethod: function () {
        return 'some value';
    }
};

Test Cases

below are the different test cases that tries to test our production code functionalities.

Test if a method get called

Similar to the sinon spies you can test a method get called or not .

get calledJavaScript

SinonStubTest.prototype.testCallMyMethodShouldCallMyMethodOneTime = function () {
    expectAsserts(1);
    var myMethodStub = this._sandbox.stub(sinonStub, 'myMethod');
    sinonStub.callMyMethod(1);
    assertTrue(myMethodStub.calledOnce);
};

Test if a method get called with expected args

it test a method get called with expected args or not.

get called with argsJavaScript

SinonStubTest.prototype.testMyMethodShouldReturnExpectedValueOnNthCall = function () {
    expectAsserts(3);
    var myMethodStub = this._sandbox.stub(sinonStub, 'myMethod');
    var arg1 = 'arg one';
    var arg2 = 'arg two';
    var firstCall = 'first call';
    var secondCall = 'second call';
    var thirdCall = 'third call';
 
    myMethodStub.onCall(0).returns(firstCall);  //onFirstCall
    myMethodStub.onCall(1).returns(secondCall); //onSecondCall
    myMethodStub.onCall(2).returns(thirdCall); //onThirdCall
    var actualValue = sinonStub.callMyMethod(1, arg1, arg2);
    assertEquals(firstCall, actualValue);
 
    actualValue = sinonStub.callMyMethod(1, arg1, arg2);
    assertEquals(secondCall, actualValue);
 
    actualValue = sinonStub.callMyMethod(1, arg1, arg2);
    assertEquals(thirdCall, actualValue);
};

Always return some value

in same way you can force the “myMethod” to always return some expected value.

always return valueJavaScript

SinonStubTest.prototype.testMyMethodShouldAlwaysReturnExpectedValue = function () {
    expectAsserts(1);
    var myMethodStub = this._sandbox.stub(sinonStub, 'myMethod');
    var expectedValue = "some expected value";
    myMethodStub.returns(expectedValue);
 
    var actualValue = sinonStub.callMyMethod(3);
    assertEquals(expectedValue, actualValue);
};

Ask stubbed method to raise an exception

“throws” will throw your expected error which could be string or object. it can help you test your error handling scenarios.

raise exception

SinonStubTest.prototype.testExceptionMethodRaiseException = function () {
    expectAsserts(2);
    var exceptionMethodStub = this._sandbox.stub(sinonStub, 'exceptionMethod');
    var error = {someKey: "TypeError"};
    exceptionMethodStub.throws(error);
 
    var actualValue = sinonStub.callMyMethod(1);
    assertTrue(exceptionMethodStub.threw());
    assertTrue(exceptionMethodStub.threw(error));
};

Asked stubbed method to returns expected callback “yieldsTo” will help you test the callbacks and force your code to call your expected callbacks.

in below code it force the “methodWithCallBack” function to call the onError callback.

yields to callback

yields to callbackJavaScript

SinonStubTest.prototype.testOnFailureOfMyMethodWithCallBackShouldReturnExpectedValue = function () {
    expectAsserts(1);
    var myMethodStub = this._sandbox.stub(sinonStub, 'methodWithCallBack');
    var expectedValue = "failure";
    myMethodStub.yieldsTo("onError");
 
    var actualValue = sinonStub.myMethodWithCallBack();
    assertEquals(expectedValue, actualValue);
};

yields to callback with args

similar to the above example you can also specify your callback args as well.

yields to callback with argsJavaScript

SinonStubTest.prototype.testOnFailureOfMyMethodWithCallBackShouldReturnExpectedValueWithArgs = function () {
    expectAsserts(1);
    var myMethodStub = this._sandbox.stub(sinonStub, 'methodWithCallBack');
    var expectedValue = "success"+'first'+ 'second';
    myMethodStub.yieldsTo("onSuccess",'first','second','third');
 
    var actualValue = sinonStub.myMethodWithCallBack();
    assertEquals(expectedValue, actualValue);
};

Download

you can find the full API reference on sinon spy documentation . Also feel free to download the full source code of this example from my github.