角单元测试控制器 - 内部控制嘲讽服务 [英] Angular unit-test controllers - mocking service inside controller
问题描述
我有以下情况:
controller.js
controller('PublishersCtrl',['$scope','APIService','$timeout', function($scope,APIService,$timeout) {
APIService.get_publisher_list().then(function(data){
});
}));
controllerSpec.js
'use strict';
describe('controllers', function(){
var scope, ctrl, timeout;
beforeEach(module('controllers'));
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new(); // this is what you missed out
timeout = {};
controller = $controller('PublishersCtrl', {
$scope: scope,
APIService: APIService,
$timeout: timeout
});
}));
it('should have scope variable equals number', function() {
expect(scope.number).toBe(3);
});
});
错误:
TypeError: Object #<Object> has no method 'get_publisher_list'
我也试过这样的事情,并没有工作:
I also tried something like this, and it didn't work:
describe('controllers', function(){
var scope, ctrl, timeout,APIService;
beforeEach(module('controllers'));
beforeEach(module(function($provide) {
var service = {
get_publisher_list: function () {
return true;
}
};
$provide.value('APIService', service);
}));
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
timeout = {};
controller = $controller('PublishersCtrl', {
$scope: scope,
APIService: APIService,
$timeout: timeout
}
);
}));
it('should have scope variable equals number', function() {
spyOn(service, 'APIService');
scope.get_publisher_list();
expect(scope.number).toBe(3);
});
});
我怎样才能解决这个问题?有什么建议?
How can i solve this? any suggestions?
推荐答案
有两种方法(或更多肯定的)。
There are two ways (or more for sure).
想象这种服务(没关系,如果它是一个工厂):
Imagining this kind of service (doesn't matter if it is a factory):
app.service('foo', function() {
this.fn = function() {
return "Foo";
};
});
通过该控制器:
app.controller('MainCtrl', function($scope, foo) {
$scope.bar = foo.fn();
});
一个方法是创建一个对象与方法,您将使用和间谍它们:
One way is just creating an object with the methods you will use and spy them:
foo = {
fn: function() {}
};
spyOn(foo, 'fn').andReturn("Foo");
然后你传递富
作为DEP到控制器。无需注射服务。这将正常工作。
Then you pass that foo
as a dep to the controller. No need to inject the service. That will work.
另一种方法是嘲笑服务,并注入嘲笑之一:
The other way is to mock the service and inject the mocked one:
beforeEach(module('app', function($provide) {
var foo = {
fn: function() {}
};
spyOn(foo, 'fn').andReturn('Foo');
$provide.value('foo', foo);
}));
当你再注入富
它会注入这一个。
When you inject then foo
it will inject this one.
在这里看到它:<一href=\"http://plnkr.co/edit/WvUIrtqMDvy1nMtCYAfo?p=$p$pview\">http://plnkr.co/edit/WvUIrtqMDvy1nMtCYAfo?p=$p$pview
对于那些与制作工作答案奋斗,
For those that struggle with making the answer work,
作为茉莉花2.0 andReturn()
成为 and.returnValue()
as of Jasmine 2.0 andReturn()
became and.returnValue()
因此,例如在从上面plunker 1号试验:
So for example in the 1st test from the plunker above:
describe('controller: MainCtrl', function() {
var ctrl, foo, $scope;
beforeEach(module('app'));
beforeEach(inject(function($rootScope, $controller) {
foo = {
fn: function() {}
};
spyOn(foo, 'fn').and.returnValue("Foo"); // <----------- HERE
$scope = $rootScope.$new();
ctrl = $controller('MainCtrl', {$scope: $scope , foo: foo });
}));
it('Should call foo fn', function() {
expect($scope.bar).toBe('Foo');
});
});
(来源: Rvandersteen )
这篇关于角单元测试控制器 - 内部控制嘲讽服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!