I'm having trouble using a mock to replace a dependency of my class when testing, using Sinon.js and Buster.js.
I'm testing class B, which has a dependency on class A. I use Sinon.js to create a mock object of class A, and pass it into an instance of class B. In my test I call the doSomething
method of object B, which then calls the getData
method of object A. (Though the getData
method is actually on A's prototype, not A itself).
But when I run the test I get the error:
TypeError: a.getData is not a function
If I try and stub the getData
method of A's prototype, then I get the error:
TypeError: Attempted to wrap getData which is already stubbed
The error occurs on the line where I'm setting mock_A.expects('getData')
. This is the classes and test I'm running:
function A(){};
A.prototype = {
"getData" : function(oDataToGet, cb) {
var aData = ['someData'];
cb(aData);
}
}
function B() {
var a;
this.setA = function(oA){
a = oA;
};
this.doSomething = function(oObj){
a.getData({}, function(aData){if(!aData){throw new Error('No data');} oObj.data = aData[0];});
}
}
var oB, assert = buster.referee.assert;
buster.testCase('myTest', {
"setUp" : function()
{
oB = new B();
},
"test_Mock" : function()
{
var mock_A = sinon.mock(new A());
oB.setA(mock_A);
// sinon.stub(A.prototype, 'getData').callsArgWith(1, ['hi']);
mock_A.expects('getData')
.withArgs({})
.once();
var oTestObj = {};
oB.doSomething(oTestObj)
mock_A.verify();
}
});
Edit 2016-03-16 to add: A workaround is to use a stubbed instance rather than a mock, and then set the method you need to check to an expectation:
var stubbed_A = sinon.createStubInstance(A);
stubbed_A.getData = sinon.expectation.create('getData')
.withArgs({})
.once();
oB.setA(stubbed_A);
var oTestObj = {};
oB.doSomething(oTestObj);
stubbed_A.getData.verify();
There is a difference between sinonJS and other mocking frameworks (like Mockito, jMock etc.) that creates this misunderstanding. In most mocking frameworks, you create the mocked dependency and inject it in the object-to-be-tested (SUT), as you did:
var mock_A = sinon.mock(new A());
oB.setA(mock_A);
However, in sinonJS, you have to inject the original object and use the generated mock object to assign expectations over the original one. So, if you change the previous 2 lines with the following, your test works as expected:
var a = new A();
var mock_A = sinon.mock(a);
oB.setA(a);
Stubs are more appropriate, when we want to control the behaviour of a dependency of the object we are testing. Mocks are more appropriate, when we want to ensure that a specific event will happen on the dependency of the object we are testing (via expectations). So, in this case, a mock object would be more suitable than a stub, as in your first attempt.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.