Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing private members in Javascript using Sinon

I'm starting to write some javascript tests and trying to figure out what the best approach is for inspecting the private members of a module constructor. For example, in the sample below i'm using the revealing module pattern to expose the public api to my module. I want to test that privateVar is correctly set during the callback of the $.getJSON ajax request.

The second test it('should update privateVar', ...), doesn't work because myModule.privateVar is (intentionally) not in the public api for the module.

So, my question is, What is the best way to test this kind of behaviour without having to make the privateVar part of the public api? Is there a better way to factor this code for testing, or maybe a way to use something like SinonJs to spy on the private member?

define('myModule',
    ['jquery'],
    function ($) {
        var
            myVar = "something",
            privateVar = "something else",

            doSomething = function() {
                return $.getJSON('http://myapi.com/do-something', { requestData : "some data" }, function(response){
                    myVar = response.data.value1;
                    privateVar = response.data.value2;
                });
            };

        return {
            doSomething : doSomething,
            myVar : myVar
        };
    }
);

define('test/test.myModule',
    ['myModule', 'chai', 'sinon', 'mocha'],
    function (myModule, chai, sinon) {

        describe("myModule", function() {
            var expect = chai.expect;

            describe('doSomething', function() {

                var value1 = 'value1 value',
                    value2 = 'value2 value';

                beforeEach(function() {
                    sinon.stub($, 'ajax').yieldsTo('success', {
                        data : { value1 : value1, value2 : value2 }
                    });
                });

                afterEach(function() {
                    $.ajax.restore();
                });

                it('should update myVar', function(done) {
                    myModule.doSomething();
                    expect(myModule.myVar).to.equal(value1);
                    done();
                });

                it('should update privateVar', function(done) {
                    myModule.doSomething();
                    expect(myModule.privateVar).to.equal(value2);
                    done();
                });
            });


        });

    }
);
like image 484
Robbie Avatar asked Feb 25 '13 11:02

Robbie


People also ask

How do you mock a variable in Sinon?

var sinon = require('sinon'); var start_end = require('./start_end'); describe("start_end", function(){ before(function () { cb_spy = sinon. spy(); }); afterEach(function () { cb_spy. reset(); }); it("start_pool()", function(done){ // how to make timer variable < 1, so that if(timer < 1) will meet start_end.

What is Sinon testing?

Sinon JS is a popular JavaScript library that lets you replace complicated parts of your code that are hard to test for “placeholders,” so you can keep your unit tests fast and deterministic, as they should be.

What is Sinon Spy ()?

The function sinon. spy returns a Spy object, which can be called like a function, but also contains properties with information on any calls made to it. In the example above, the firstCall property has information about the first call, such as firstCall. args which is the list of arguments passed.

Can you use Sinon with jest?

Sinon. js mocks ship as part of the Sinon. js library which can be plugged in and used in combination with other testing frameworks like Mocha and assertion libraries like Chai. Jest mocks, on the other hand, ship as part of the Jest framework, which also ships with its own assertions API.


2 Answers

What you are talking about here unfortunately requires an integration test, you wish to test that a variable is set as a result of an external operation, You should trust that the external method just works for your test by stubbing it out in your tests as you have done with sinon this takes care of the external call.

What you need to be able to do is to control the conditions of the test (lets say non authenticated and authenticated) then test what the result of the function is in that instance. As a rule I don't normally test private members at all but I do test desired behaviour resulting from known good and bad values..

I also read this a little while ago, which discusses private vars.

like image 160
krystan honour Avatar answered Sep 19 '22 10:09

krystan honour


The only way you can access your private variables this way is is to add a public getter that you can later call in your test to verify the state:

In your class:

getPrivateVar : function(){ return privateVar; }

Then add to return statement:

return { getPrivateVar : getPrivateVar, };

like image 24
rochal Avatar answered Sep 23 '22 10:09

rochal