angularjs - Angular Unit Testing - Mocking methods/closures in same service -
i'm trying unit test angular service using sinonjs, have been running issue , hoping possibly shed light on why occurring. have reconstructed current project illustrate problem @ hand.
i have provided demo
i have service, peopleservice
:
(function (){ angular.module('myapp') .factory('peopleservice', peopleservice); peopleservice.$inject = ['$q']; function peopleservice ($q){ var people = ['homer', 'marge', 'bart', 'lisa', 'maggie']; // in actual project, makes http request function getfamily () { return people; } function getadults (){ var family = getfamily(); return family.filter(function (person){ return person === 'homer' || person === 'marge'; }); } return { getfamily: getfamily, getadults: getadults } } }());
in service, method getadults
uses getfamily
, filters results, , returns data.
in unit test, trying mock getfamily
, see if method being called. problem presents itself...
first thing tried stubbing out method , overwriting current method, so:
beforeeach(function (){ module('myapp'); inject(function (_peopleservice_){ peopleservice = _peopleservice_; // service sinon.stub(peopleservice, 'getfamily'); // stub }); });
i go test whether getadults
calls getfamily
method:
it('getadults should call "getfamily" once', function(){ peopleservice.getadults(); expect(peopleservice.getfamily.calledonce).tobe(true); });
the test fails , stubbed method not called...
i debug , find out although function has in fact changed:
the service still holds reference (closure) method used when service created:
my initial thought didn't stub method correctly. attempted overwriting method using $provide
($provide.value
) $injector decorator
, ended getting same result (closure held onto original method).
a solution use this
:
function getadults (){ var family = this.getfamily(); // <-- using this.getfamily reference mock return family.filter(function (person){ return person === 'homer' || person === 'marge'; }); }
however, not understand why have this.
in short, know:
- how mock method in same service without having use
this
- how mock out closure variable in unit test
thank time.
when stub method on object, property of object overriden, not original function references.
take, example, code:
function myfunction () {}; var myobj = { prop: myfunction }; myobj.prop === myfunction; // true myobj.prop = 'changed'; typeof myfunction === 'function'; // true myobj.prop === myfunction; // false
changing myobj.prop
did not change original function, myfunction
still exists in own right. myobj.prop
, however, has lost reference myfunction
. if in sinon world, stubbing changed reference of myobj.prop
stub object.
this why when testing code in service calls function in same service, code needs reference same object returned service. if want avoid using this
keyword everywhere, can structure service so:
angular.module('myapp') .factory('peopleservice', peopleservice); peopleservice.$inject = ['$q']; function peopleservice ($q){ var service = { getfamily: getfamily, getadults: getadults }; return service; function getfamily () { // ... } function getadults (){ var family = service.getfamily(); // <-- reference service.getfamily() // ... } }
Comments
Post a Comment