How to test data polling on AngularJS with Jasmine? -
i have trouble test data polling in controller
controller logic looks this
$oninit() { this.requestrootlocations(); this.startdatapolling(); } private startdatapolling() { this.stop = this.$interval(() => this.requestrootlocations() , this.data_polling_interval); } private requestrootlocations() { this.locationsservice.requestrootelements().then(function (locationitem) { ... this.entitylist = (locationitem["locations"] instanceof array) ? locationitem["locations"] : []; }.bind(this), function () { console.log("error on loading locations data."); }); }
update: http request in service:
public requestrootelements() { return this.$http.get(this.api + "locations").then((response) => response.data); }
this works fine expected.
the test case looks this
it("should call http request on intervals", function () { ctrl.$oninit(); $httpbackend.whenget(api + "locations").respond(200, locationdata); // advance in time 1 seconds $interval.flush(1000); $httpbackend.expectget(api + "locations"); // after 1 seconds locations should called once $httpbackend.flush(); expect(ctrl.counts.length).tobe(4); expect(ctrl.entities.length).tobe(6); $interval.flush(datapollinginterval); $httpbackend.expectget(api + "locations"); //does not work, why? $httpbackend.flush(); // after second call data should same in case expect(ctrl.counts.length).tobe(4); expect(ctrl.entities.length).tobe(6); });
but on second expectget error
error: unsatisfied requests: /apiv1/locations
the problem here units aren't isolated. integration test (controller + service + $interval), not unit test. when test becomes red, it's not possible of units has failed.
the proper strategy unit-test mock tested unit (controller). $interval
can optionally mocked too, , don't need test how works - tested angular.
constructor(...) { ... // bind callback method this.datapollinghandler = this.datapollinghandler.bind(this); } $oninit() { this.requestrootlocations(); this.stop = this.$interval(this.datapollinghandler, this.data_polling_interval); } private datapollinghandler() { this.requestrootlocations() }
and can tested like
spyon(ctrl, 'requestrootlocations'); // unbind callback method ctrl.datapollinghandler.call(null); expect(ctrl.requestrootlocations).tohavebeencalled(); ... var intervalpromise = $q.resolve(); var intervalmock = jasmine.createspy().and.returnvalue(intervalpromise); var ctrl = $controller(..., { $interval: intervalmock }); ctrl.$oninit(); expect(ctrl.stop).tobe(intervalpromise); expect($intervalstub).tohavebeencalledwith(ctrl.datapollinghandler, 1000); ... var locationsservicemock = { requestrootlocations: jasmine.createspy().and.returnvalue($q.resolve(locationdata)); } var ctrl = $controller(..., { locationsservice: locationsservicemock }); // ctrl.requestrootlocations can tested ...
it ok have both unit , integration tests in suite, when proper controller , service unit tests exist, integration test becomes redundant.
Comments
Post a Comment