Jasmine - how to spyOn instance methods
Solution 1
Where you went wrong was your understanding of how to refer to methods in JavaScript in a static context. What your code is actually doing is spying on ClassName.doA
(that is, the function attached to the ClassName
constructor as the property doA
, which is not what you want).
If you want to detect when that method gets called on any instance of ClassName
anywhere, you need to spy on the prototype.
beforeEach(function() {
spyOn(ClassName.prototype, 'doA');
});
it('should call doA', function() {
myFunc();
expect(ClassName.prototype.doA).toHaveBeenCalled();
});
Of course, this is assuming that doA
lives in the prototype chain. If it's an own-property, then there is no technique that you can use without being able to refer to the anonymous object in myFunc
. If you had access to the ClassName
instance inside myFunc
, that would be ideal, since you could just spyOn
that object directly.
P.S. You should really put "Jasmine" in the title.
Solution 2
Let’s do some code refactoring as we want implement constructor injection pattern as James Shore mentions that:
Dependency injection means giving an object its own instance variables. Really. That’s it.
var data = {};
var stuff = new ClassName()
var myFunc = function(stuff) { // move step of creation new object outside
data.stuff = stuff.doA().doB().doC();
};
And time for some tests
function ClassName() {
}
var data = {};
var stuff = new ClassName()
var myFunc = function(stuff) {
data.stuff = stuff.doA().doB().doC();
};
describe('stub for ClassName implementation', function() {
var stubStuff = {
doA: function() {
return stubStuff
},
doB: function() {
return stubStuff
},
doC: function() {
return stubStuff
}
}
beforeEach(function() {
spyOn(stubStuff, 'doA').and.callThrough();
});
it('calls "doA" on "myFunc" exection', function() {
myFunc(stubStuff);
expect(stubStuff.doA).toHaveBeenCalled();
});
});
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
sfletche
Updated on April 24, 2020Comments
-
sfletche about 4 years
I have a function
var data = {}; var myFunc = function() { data.stuff = new ClassName().doA().doB().doC(); };
I'd like to test that
doA
,doB
, anddoC
were all called.I tried spying on the instance methods like this
beforeEach(function() { spyOn(ClassName, 'doA'); }; it('should call doA', function() { myFunc(); expect(ClassName.doA).toHaveBeenCalled(); });
but that just gives me a "doA() method does not exist" error.
Any ideas?