这是我的控制者:
angular.module("AuthenticationApp", ["BaseApp"])
.controller("AuthCtrl", ["$http", "BaseService", function($http, BaseService) {
var self = this;
BaseService.fetch.stuffs()
.then(function(data) {
self.stuffs = data;
});
}]);
我的BaseService
(我需要模拟的工厂):
angular.module("BaseApp", ["ngRoute"])
.factory("BaseService", ["$http", "$q", function($http, $q) {
var self = this;
self.fetch = {
stuffs: function() {
return $http.get("/api/stuffs/")
.then(function(response) {
return response.data;
});
}
};
return self;
}]);
我不知道从哪里开始。我试过的是:
describe('Controller: AuthCtrl', function() {
var ctrl, mockBaseService;
beforeEach(function() {
mockBaseService = {
stuffs: 'test',
fetch: {
stuffs: function() {
return {
then: function() {
return {stuffs: "stuffs"};
},
}
},
},
};
spyOn(mockBaseService.fetch, 'stuffs');
module('BaseApp', function($provide) {
$provide.value('BaseService', mockBaseService);
});
module('AuthenticationApp');
inject(function($controller) {
ctrl = $controller('AuthCtrl', {
});
});
});
it('BaseService.fetch.stuffs should be called on page load', function() {
expect(mockBaseService.fetch.stuffs).toHaveBeenCalled();
expect(ctrl.stuffs).toBe({stuffs: "stuffs"});
});
});
但是当我测试这段代码时,我收到一条错误说:
TypeError: Cannot read property 'then' of undefined
at new <anonymous> (/home/user/Documents/ebdjango/ebdjangoapp/static/js/home.js:15:11)
home.js
第15行是控制器中的这一行:
return $http.get("/api/stuffs/")
.then(function(response) { // line 15
return response.data;
});
如何正确模仿?
编辑:我阅读了评论中提到的文档,并将mockBaseService
更改为:
describe('Controller: AuthCtrl', function() {
var ctrl, mockBaseService;
beforeEach(function() {
// create promise
var deferred = $q.defer();
var promise = deferred.promise;
// make promise.then return {stuffs: "stuffs"}
promise.then(function(value) { return {stuffs: "stuffs" }; });
mockBaseService = {
stuffs: 'stuffs',
fetch: {
stuffs: function() {
return promise;
},
},
};
spyOn(mockBaseService.fetch, 'stuffs');
module('BaseApp', function($provide) {
$provide.value('BaseService', mockBaseService);
});
module('AuthenticationApp');
inject(function($controller) {
ctrl = $controller('AuthCtrl', {
});
});
});
it('BaseService.fetch.stuffs should be called on page load', inject(function($rootScope) {
deferred.resolve('test');
$rootScope.$apply();
expect(mockBaseService.fetch.stuffs).toHaveBeenCalled();
expect(ctrl.stuffs).toBe({stuffs: "stuffs"});
}));
});
但是这会返回ReferenceError: $q is not defined
错误。我尝试像这样注射_$q_
:
beforeEach(inject(function(_$q_) {
$q = _$q_;
// ... everything else goes here... //
但后来我收到错误Error: Injector already created, can not register a module!
。在此处:injector already created. can not register a module它说如果我们在module('someApp')
之前inject($someDependency)
,则可以解决此问题。但我做不到
module('BaseApp', function($provide) {
$provide.value('BaseService', mockBaseService);
});
注入_$q_
之前,因为$q
用于mockBaseService
。我从哪里开始?
答案 0 :(得分:1)
嘲笑我总是做的承诺
1) spyOn(service,'method').andCallFake( $q.when( Fixture.data() ) )
不要创建那个mockBaseService,我之前已经做过了,而且很多东西都没有写 它也可以使用AngularJS内置拦截$ http即
的方式2) $httpBackend.when('GET', '/url').respond(Fixture.data())
我绝对更喜欢1)因为我喜欢在进行测试时将自己隔离在某一层。这归结为我猜的味道