我正在尝试使用单独的 json 文件中的模拟响应运行单元测试。当我使用 $q 返回在我的 OpsService 中手动解决的 promise 时,测试工作正常,但是当我试图将它们变成实际的 $http 请求以返回实际的 json 文件时,它们不再有效。
编辑:我已经尝试过 $httpBackend.flush()
、$rootScope.$apply()
和 $rootScope.$digest()
但这些似乎都无法解决 promise 。
我的服务:
OpsService.service('OpsService', function ($q, $http) {
this.get = {
bigTen : function () {
// var defer = $q.defer();
// defer.resolve({"data":{"alltime":125077,"record":{"date":"2016-07-19","count":825},"today":281}});
// return defer.promise;
return $http({
method: 'GET',
url: '/jsonMocks/api/big-ten.json'
}).then(function (response) {
console.log('bigTen data');
console.log(response);
return response;
}, function (error) {
console.log('ERROR');
console.log(error);
});
},
dashboardData : function () {
console.log('blahhhhh');
return $http({
method: 'GET',
url: '/jsonMocks/api/dashboard-data.json'
}).then(function (response) {
console.log('dasbhoard data');
console.log(response);
return response;
}, function (error) {
console.log('ERROR');
console.log(error);
});
}
};
return this;
});
我的 Controller :
homeModule.controller('HomeController', function ($scope, OpsService) {
var ctrl = this;
ctrl.loading = {
topMetrics: true,
dashboardData: true
};
function init() {
ctrl.topMetricData();
ctrl.getDashboardData();
ctrl.initialized = true;
}
ctrl.topMetricData = function () {
ctrl.loading.topMetrics = true;
console.log('in topMetricData()');
return OpsService.get.bigTen().then(function (bigTen) {
console.log('bigTenControllerCallback');
ctrl.loading.topMetrics = false;
return bigTen;
});
};
ctrl.getDashboardData = function () {
ctrl.loading.dashboardData = true;
console.log('in getDashboardData()');
return OpsService.get.dashboardData().then(function (response) {
console.log('getDashboardDataController Callback');
ctrl.loading.dashboardData = false;
return dashboardData;
});
};
init();
});
我的测试:
describe('home section', function () {
beforeEach(module('ngMockE2E'));
beforeEach(module('templates-app'));
beforeEach(module('templates-common'));
beforeEach(module('LROps.home'));
var $rootScope, $scope, $httpBackend, createController, requestHandler;
beforeEach(inject(function($injector, _$rootScope_, _$controller_, _OpsService_) {
$rootScope = _$rootScope_;
$httpBackend = $injector.get('$httpBackend');
var bigTenJson = readJSON('jsonMocks/api/big-ten.json');
console.log(bigTenJson);
$httpBackend.when('GET', '/jsonMocks/api/big-ten.json')
.respond(200, { data: bigTenJson });
// .respond(200, { data: 'test1' });
var dashboardDataJson = readJSON('jsonMocks/api/dashboard-data.json');
console.log(dashboardDataJson);
$httpBackend.when('GET', '/jsonMocks/api/dashboard-data.json')
.respond(200, { data: dashboardDataJson });
// .respond(200, { data: 'test2' });
var $controller = _$controller_;
createController = function() {
$scope = $rootScope.$new();
return $controller('HomeController', {
$scope : $scope,
OpsService : _OpsService_
});
};
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should retrieve big ten data', inject(function () {
$httpBackend.expect('GET', '/jsonMocks/api/big-ten.json');
$httpBackend.expect('GET', '/jsonMocks/api/dashboard-data.json');
// Controller Setup
var ctrl = createController();
// Initialize
$rootScope.$apply();
$rootScope.$digest();
expect(ctrl.topMetrics.display.messages.count).toEqual(745);
}));
});
所以,我的 console.log() 都没有在 .then() 回调中触发。如果我改回返回一个 $q.defer().resolve(response).promise
对象,它似乎工作正常。
注意:我正在使用 karma-read-json 来读取 JSON 文件并在我的测试中做出相应的响应。据我所知,它们被正确阅读,只是 promise 没有得到解决,所以 .then() 回调可以执行。
最佳答案
首先,每个断言请求都应该是模拟请求。请求应该用 $httpBackend.flush()
刷新,它触发一个摘要,$rootScope.$apply()
和 $rootScope.$digest()
(它们相互重复)不应该被调用。
第二件事是它不应该在 Controller 规范中完成! Controller 是一个依赖于服务的独立单元,它应该与模拟服务隔离测试。 OpsService
是一个不同的单元。
it('should retrieve big ten data', inject(function () {
$httpBackend.expect('GET', '/jsonMocks/api/big-ten.json').respond(200, ...);
$httpBackend.expect('GET', '/jsonMocks/api/dashboard-data.json').respond(200, ...);
OpsService.get.bigTen().then(function (result) {
expect(result)...
}, function (err) {
throw err;
});
OpsService.get.dashboardData()...
$httpBackend.flush();
}));
it('should test a controller', inject(function () {
var OpsServiceMock = { get: {
bigTen: jasmine.createSpy().and.returnValue(...),
dashboardData: jasmine.createSpy().and.returnValue(...)
} };
$scope = $rootScope.$new();
var ctrl = $controller('HomeController', {
$scope : $scope,
OpsService : OpsServiceMock
});
$rootScope.$digest();
expect(OpsServiceMock.get.bigTen).toHaveBeenCalled();
expect(OpsServiceMock.get.dashboardData).toHaveBeenCalled();
expect...
}));
关于javascript - 使用 $http 请求的 AngularJS 单元测试永远不会触发 .then() 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39021000/