Angularjs 用Jasmine测试角度异步服务
我试图用Jasmine(集成测试)测试一个真正的http调用,但是当我调用一个使用$http.get的方法时,它会超时,服务器永远不会被调用 我知道我应该注入$http的实现,但不确定应该在哪里注入 searchSvcAngularjs 用Jasmine测试角度异步服务,angularjs,jasmine,integration-testing,Angularjs,Jasmine,Integration Testing,我试图用Jasmine(集成测试)测试一个真正的http调用,但是当我调用一个使用$http.get的方法时,它会超时,服务器永远不会被调用 我知道我应该注入$http的实现,但不确定应该在哪里注入 searchSvc app.service('searchSvc', ['$http', '$q', searchSvc]); function searchSvc($http, $q) { return { search: function(text) { console.
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));
}
};
}
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();
});
});
searchSpec
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));
}
};
}
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();
});
});
如果您使用承诺,您可以在这里找到如何处理承诺,这是一种假设,但如果您同时包括
ngMock
&ngMockE2E
模块作为应用程序模块的依赖项(ngMock
需要在依赖项列表中位于ngMockE2E
之前)您应该能够使用ngMockE2E
模块提供的$httpBackend
服务来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();
});
});
});
当我使用ngMock进行单元测试时,我使用这个解决方案来进行真正的HTTP调用。我主要使用它进行调试、完成测试、获取JSON示例等 我在我的博客上写了一篇关于解决方案的更详细的帖子: 解决办法如下:
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>
它是如何工作的?
它使用ngMockE2E版本的$httpBackEndProvider,它为我们提供了测试中使用的传递函数。这是顾名思义的,允许本地HTTP调用通过
我们需要在不使用$BrowserProvider的伪版本的情况下重新定义ngMock模块,因为这是在使用ngMock的单元测试中阻止真正HTTP调用的原因。我不确定它是否允许您这样做。。。这不是真正的单元测试。这是一个集成测试。我相信这样做的目的是使用
$httpBackend
mock测试调用服务器的代码,并使用自己的单元测试测试服务器本身,最后编写端到端测试,以确保它们都能正常工作。这些将使用量角器运行,并在没有模拟的情况下测试实际应用程序。对,我从来没有说过这是一个单元测试。我正在尝试使用Jasmine进行集成测试和单元测试。我懂了。现在我也很好奇。我删除了angular Mock,从一个实际的angular模块中引用了$http并尝试了这一点,但它也从来没有解决这个问题。我认为在一个正常运行的应用程序中,有一些应该在内部发生的事情在这里是不会发生的。有点像我们在测试中必须手动调用$scope.$digest
。我猜这与依赖注入的工作方式有关吧?我见过一些控制器的例子,其中可以在Jasmine块中提供依赖项的实现,但找不到servicesCheck的符号:嗯,我不确定这是否是承诺问题,因为searchSvc.search被触发。问题是服务器从来没有被调用过。感谢您发布此消息!我仍然感到震惊的是,在茉莉花中进行端到端测试是如此的困难。。我一定会尝试你的方法并向你汇报。再次感谢