AngularJs:茉莉花测试服务
我做了这个控制器AngularJs:茉莉花测试服务,angularjs,jasmine,karma-runner,Angularjs,Jasmine,Karma Runner,我做了这个控制器 app.controller('controller',['$scope','httpServices',function($scope,httpServices){ $scope.items= undefined; httpServices.getItems( function(items){ $scope.items= items; }); }]); 我写了这个测试 describe('controller', functi
app.controller('controller',['$scope','httpServices',function($scope,httpServices){
$scope.items= undefined;
httpServices.getItems( function(items){
$scope.items= items;
});
}]);
我写了这个测试
describe('controller', function () {
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
controller = $controller('controller', {
'$scope': scope
});
}));
it('defined', function () {
expect(scope.items).toBeUndefined();
})
});
如何在调用服务之后测试scope.items?我假设您的服务httpServices正在发出一些http请求。因此,您应该使用该服务来测试控制器 类似这样,请注意我在代码中的注释:
describe('Your specs', function() {
var $scope,
$controller,
$httpBackend;
// Load the services's module
beforeEach(module('yourApp'));
beforeEach(inject(function(_$controller_, $rootScope, _$httpBackend_) {
$scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
$controller = _$controller_;
//THIS LINE IS VERY IMPORTANT, HERE YOU HAVE TO MOCK THE RESPONSE FROM THE BACKEND
$httpBackend.when('GET', 'http://WHATEVER.COM/API/SOMETHING/').respond({});
var createController = function(){
$controller('controller', {$scope: $scope});
}
}));
describe('Your controller', function() {
it('items should be undefined', function() {
createController();
expect(scope.items).toBeUndefined();
});
it('items should exist after getting the response from the server', function () {
//THIS LINE IS ALSO VERY IMPORTANT, IT EMULATES THE RESPONSE FROM THE SERVER
$httpBackend.flush();
expect(scope.items).toBeDefined();
});
});
});
问题标题说明这是为了测试服务,但问题代码看起来像是在尝试测试控制器。此答案描述了如何测试控制器 如果您正在测试调用httpServices.getItems的控制器,那么您需要模拟它/存根getItems,以便 在测试中控制它 不假设真实的httpServices.getItems有任何行为。毕竟,您测试的是控制器,而不是服务。 一种方法是在创建控制器之前调用beforeach块,提供一个getItems的伪实现,该实现只保存传递给它的回调
var callback;
beforeEach(inject(function(httpServices) {
callback = null;
spyOn(httpServices, 'getItems').and.callFake(function(_callback_) {
callback = _callback_;
});
});
在测试中,您可以调用这个回调函数,传入一些虚假数据,并测试在作用域上是否正确设置了这些数据
it('saves the items passed to the callback on the scope', function () {
var testItems = {};
callback(testItems);
expect($scope.items).toBe(testItems);
});
可以看出,这一点正在发挥作用
如果您确实想测试httpServices.getItems本身,则需要进行单独的测试。假设getItems调用$http,那么您很可能需要使用$httpBackend来处理模拟响应。最有可能的是,这些测试不会实例化任何控制器,并且我怀疑不需要在任何范围上执行任何操作。在第二个测试中,它应该是expectscope.items.toBeDefined@当然,我只是改变了。但是为什么呢?旧代码是100%等效的:expectscope.items.not.toBeUndefined与expectscope.items.tobedefinedah my bad!我不知道,我道歉@阿披舍卡因不担心,不需要道歉。我最初做的是expectscope.items.not.toBeUndefined,因为在第一次调用中我做的是expectscope.items.toBeUndefined,我认为看到差异会更加明显。但都是一样的;在我的测试中,我一直使用.toBeDefined和.not.toBeDefined,并且从不知道变体的存在。正如你所说,两者都是一样的,使用其中一种只是个人的选择-你为什么不从httpServices.getItems返回承诺?