我试图在单独的json文件中使用模拟响应运行单元测试。当我使用$ q返回在我的OpsService中手动解析的promises时,测试工作正常,但是当我尝试将它们转换为实际的$ http请求以返回实际的json文件时,它们不再起作用。
编辑:我已尝试过$httpBackend.flush()
,$rootScope.$apply()
和$rootScope.$digest()
,但这些似乎都没有解决这些承诺。
我的服务:
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;
});
我的控制器:
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文件并在我的测试中做出相应的响应。据我所知,他们正在被正确阅读,只是承诺没有得到解决,所以.then()回调可以执行。
答案 0 :(得分:4)
首先,每个声明的请求都应该被模拟请求。请求应使用$httpBackend.flush()
刷新,它会触发摘要,$rootScope.$apply()
和$rootScope.$digest()
(它们相互重复)不应该被调用。
第二件事是它不应该在控制器规范中完成!控制器是一个依赖于服务的独立单元,它应该与模拟服务隔离进行测试。 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...
}));
答案 1 :(得分:0)
编辑:
查看documentation for $httpBackend,expect
和when
方法无法协同工作。他们设置后端的选项不同。
expect
看起来会增加对呼叫发生的期望,并为您提供一个.respond(),您可以对结果进行调用以提供响应内容。
when
只是让您为特定回复设置回复,而不会实际说出您的期望。
因此,在您的测试中,expect
来电会覆盖您所做的when
定义,并且不会返回任何回复,因为您没有对其进行配置。
所以,我认为你可以摆脱期望并在你的控制器之后放一个flush
:
it('should retrieve big ten data', inject(function () {
// Controller Setup
var ctrl = createController();
$httpBackend.flush();
// Initialize
$rootScope.$apply();
$rootScope.$digest();
expect(ctrl.topMetrics.display.messages.count).toEqual(745);
}));
或者将when
中的beforeEach
更改为expect
,然后您可能不会需要flush
。