我正在尝试使用Jasmine(集成测试)测试一个真正的http调用,但是当我调用一个使用$ http.get的方法时,它会超时并且服务器永远不会被调用。
我知道我应该注入$ http的实现,但不确定应该在哪里发生。
searchSvc
app.service('searchSvc', ['$http', '$q', searchSvc]);
function searchSvc($http, $q) {
return {
search: function(text) {
console.log('svc.search called with ', text); // this does get called
return $q.when($http.get('/search/' + text));
}
};
}
searchSpec
describe("searchTest", function() {
var ctrl, svc, $http;
beforeEach(function () {
module('testApp');
inject(function(_$controller_, searchSvc, _$http_){
ctrl = _$controller_('searchCtrl');
svc = searchSvc;
$http = _$http_;
})
});
it('test server search', function(done) {
svc.search('re').then(function(result) {
console.log('promise then'); // this never gets called, because server never gets called
expect(result).not.toBeNull();
expect(result.data).not.toBeNull();
expect(result.data.length).toBeGreaterThan(0);
done();
});
});
答案 0 :(得分:0)
如果你使用promises,你可以在http://entwicklertagebuch.com/blog/2013/10/how-to-handle-angularjs-promises-in-jasmine-unit-tests/
找到如何处理它们的方法答案 1 :(得分:0)
这是一种假设,但如果你同时包含ngMock
和& ngMockE2E
模块作为您的应用模块的依赖项(ngMock
需要在依赖项列表中ngMockE2E
之前),您应该能够使用$httpBackend
提供的ngMockE2E
服务{1}}模块passThrough
在您的测试规范中对搜索api调用实际后端。
尝试这样的事情,看看它是否有效:
describe("searchTest", function() {
var ctrl, svc, $httpBackend;
beforeEach(function () {
module('testApp');
inject(function(_$controller_, searchSvc, _$httpBackend_){
$httpBackend = _$httpBackend_;
ctrl = _$controller_('searchCtrl');
svc = searchSvc;
});
});
it('test server search', function(done) {
$httpBackend.whenGET(/^\/search\//).passThrough();
svc.search('re').then(function(result) {
console.log('promise then'); // this never gets called, because server never gets called
expect(result).not.toBeNull();
expect(result.data).not.toBeNull();
expect(result.data.length).toBeGreaterThan(0);
done();
});
});
});
答案 2 :(得分:0)
这是我在使用ngMock进行单元测试时用来进行真正的HTTP调用的解决方案。我主要用它来调试,完成测试,获取JSON示例等。
我在博客上写了一篇关于解决方案的更详细的帖子:How to Unit Test with real HTTP calls using ngMockE2E & passThrough。
解决方案如下:
angular.mock.http = {};
angular.mock.http.init = function() {
angular.module('ngMock', ['ng', 'ngMockE2E']).provider({
$exceptionHandler: angular.mock.$ExceptionHandlerProvider,
$log: angular.mock.$LogProvider,
$interval: angular.mock.$IntervalProvider,
$rootElement: angular.mock.$RootElementProvider
}).config(['$provide', function($provide) {
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
$provide.decorator('$$rAF', angular.mock.$RAFDecorator);
$provide.decorator('$$asyncCallback', angular.mock.$AsyncCallbackDecorator);
$provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
$provide.decorator('$controller', angular.mock.$ControllerDecorator);
}]);
};
angular.mock.http.reset = function() {
angular.module('ngMock', ['ng']).provider({
$browser: angular.mock.$BrowserProvider,
$exceptionHandler: angular.mock.$ExceptionHandlerProvider,
$log: angular.mock.$LogProvider,
$interval: angular.mock.$IntervalProvider,
$httpBackend: angular.mock.$HttpBackendProvider,
$rootElement: angular.mock.$RootElementProvider
}).config(['$provide', function($provide) {
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
$provide.decorator('$$rAF', angular.mock.$RAFDecorator);
$provide.decorator('$$asyncCallback', angular.mock.$AsyncCallbackDecorator);
$provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
$provide.decorator('$controller', angular.mock.$ControllerDecorator);
}]);
};
在ngMock之后包含此源文件,例如:
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript" src="angular-mocks.js"></script>
<!-- this would be the source code just provided -->
<script type="text/javascript" src="ngMockHttp.js"></script>
describe('http tests', function () {
beforeEach(module('moviesApp'));
var $controller;
var $httpBackend;
var $scope;
describe('real http tests', function() {
beforeEach(angular.mock.http.init);
afterEach(angular.mock.http.reset);
beforeEach(inject(function(_$controller_, _$httpBackend_) {
$controller = _$controller_;
$scope = {};
$httpBackend = _$httpBackend_;
// Note that this HTTP backend is ngMockE2E's, and will make a real HTTP request
$httpBackend.whenGET('http://www.omdbapi.com/?s=terminator').passThrough();
}));
it('should load default movies (with real http request)', function (done) {
var moviesController = $controller('MovieController', { $scope: $scope });
setTimeout(function() {
expect($scope.movies).not.toEqual([]);
done();
}, 1000);
});
});
});
它使用ngMockE2E的$ httpBackEndProvider版本,它为我们提供了我们在测试中使用的 passThrough 函数。这就像名称所示,并允许本机HTTP调用通过。
我们需要在没有虚假版本的$ BrowserProvider的情况下重新定义ngMock模块,因为这会阻止使用ngMock的单元测试中的真实HTTP调用。