我无法在控制器中测试数据轮询
控制器逻辑看起来像这样
$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.");
});
}
更新 服务中的http请求:
public requestRootElements() {
return this.$http.get(this.API + "locations").then((response) => response.data);
}
这样可以正常工作。
测试用例看起来像这样
it("should call http request on intervals", function () {
ctrl.$onInit();
$httpBackend.whenGET(api + "locations").respond(200, locationData);
// advance in time by 1 seconds
$interval.flush(1000);
$httpBackend.expectGET(api + "locations");
// after 1 seconds locations should be 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 the second call the data should be the same in this case
expect(ctrl.counts.length).toBe(4);
expect(ctrl.entities.length).toBe(6);
});
但是在第二个期望的GET是一个错误
错误:请求不满意:GET / apiv1 / locations
答案 0 :(得分:0)
这里的问题是单位不是孤立的。这是集成测试(控制器+服务+ $间隔),而不是单元测试。当测试变为红色时,无法确定哪个单元出现故障。
对此进行单元测试的正确策略是模拟除测试单元(控制器)之外的所有内容。 $interval
也可以选择性地进行模拟,我们并不需要测试它是如何工作的 - 这已经被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()
}
它可以像
一样进行测试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 });
// now ctrl.requestRootLocations can be tested
...
可以在套件中进行单元测试和集成测试,但是当存在适当的控制器和服务单元测试时,集成测试就变得多余了。