[英]How to mock AngularJS promises using Jasmine / Karma?
This is my controller: 这是我的控制器:
angular.module("AuthenticationApp", ["BaseApp"])
.controller("AuthCtrl", ["$http", "BaseService", function($http, BaseService) {
var self = this;
BaseService.fetch.stuffs()
.then(function(data) {
self.stuffs = data;
});
}]);
This my BaseService
(the factory I need to mock): 这是我的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;
}]);
I have no idea where to start. 我不知道从哪里开始。 What I tried was this: 我试过的是:
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"});
});
});
But when I test this code, I get an error saying: 但是,当我测试此代码时,出现错误消息:
TypeError: Cannot read property 'then' of undefined
at new <anonymous> (/home/user/Documents/ebdjango/ebdjangoapp/static/js/home.js:15:11)
home.js
line 15 is this line in the controller: home.js
第15行是控制器中的以下行:
return $http.get("/api/stuffs/")
.then(function(response) { // line 15
return response.data;
});
How do I mock this correctly? 如何正确模拟呢?
Edit: I read the documentation mentioned in the comments and and changed up mockBaseService
to this: 编辑:我阅读了注释中提到的文档,然后将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"});
}));
});
But this returns a ReferenceError: $q is not defined
error. 但这会返回ReferenceError: $q is not defined
错误。 I tried injecting _$q_
like so: 我尝试像这样注入_$q_
:
beforeEach(inject(function(_$q_) {
$q = _$q_;
// ... everything else goes here... //
But then I get an error saying Error: Injector already created, can not register a module!
但是然后我收到一条错误消息,提示Error: Injector already created, can not register a module!
. 。 Here: injector already created. 此处: 喷油器已创建。 can not register a module it says this issue can be solved if we do module('someApp')
before inject($someDependency)
. 无法注册一个模块,它说如果我们在inject($someDependency)
之前执行module('someApp')
,则可以解决此问题。 But I can't do 但是我做不到
module('BaseApp', function($provide) {
$provide.value('BaseService', mockBaseService);
});
before injecting _$q_
since $q
is used for mockBaseService
. 在注入_$q_
之前,因为$q
用于mockBaseService
。 Where do I go from here? 我从这里去哪里?
to mock promises I always do 嘲笑我一直都在做
1) spyOn(service,'method').andCallFake( $q.when( Fixture.data() ) )
Do not create that mockBaseService, I've done that before and its a lot to write for nothing It's also possible to use AngularJS built in way of intercepting $http ie 不要创建那个模拟数据库服务,我之前已经做过了,而且很多事情都没有写。也可以使用以拦截$ http的方式构建的AngularJS。
2) $httpBackend.when('GET', '/url').respond(Fixture.data())
I definitely prefer 1) as I like to isolate myself in a certain layer when doing testing. 我绝对喜欢1),因为我喜欢在进行测试时将自己隔离在特定的层中。 It comes down to a matter of taste I guess 我想这取决于口味
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.