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('', { 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();
});
});
});
}
);
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();
});
});
});
}
);
Share
Improve this question
edited Feb 27, 2013 at 23:25
Robbie
asked Feb 25, 2013 at 11:56
RobbieRobbie
19.5k4 gold badges43 silver badges45 bronze badges
2
- This should shed some light on the topic of testing private members: stackoverflow.com/questions/105007/… – Aditya Manohar Commented Feb 25, 2013 at 12:02
- @AdityaManohar thanks for the link. In my case i am actually testing a public method, but i want to ensure that it correctly set a non public property. – Robbie Commented Feb 25, 2013 at 12:10
4 Answers
Reset to default 6What 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.
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, };
Actually why test a private variable? It is not possible/difficult. And what is the purpose of that variable? If it is going to be passed on as a argument to function, you can of-course test the function by spying if the function is called with the specific value, which was assigned to the private variable.
You can use rewire
let revertBack = renderCtrl.__set__(privateMember,substituteMember);
to revert back just call revertBack(); For more details see https://www.npmjs.com/package/rewire