Unit testing 角度单元测试控制器-控制器内模拟服务

Unit testing 角度单元测试控制器-控制器内模拟服务,unit-testing,angularjs,karma-runner,karma-jasmine,Unit Testing,Angularjs,Karma Runner,Karma Jasmine,我有以下情况: controller.js controller('PublishersCtrl',['$scope','APIService','$timeout', function($scope,APIService,$timeout) { APIService.get_publisher_list().then(function(data){ }); })); 'use strict'; describe('controllers', funct

我有以下情况:

controller.js

controller('PublishersCtrl',['$scope','APIService','$timeout', function($scope,APIService,$timeout) {

    APIService.get_publisher_list().then(function(data){

            });
 }));
'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);
    });
});
controllerSpec.js

controller('PublishersCtrl',['$scope','APIService','$timeout', function($scope,APIService,$timeout) {

    APIService.get_publisher_list().then(function(data){

            });
 }));
'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'
我怎样才能解决这个问题?有什么建议吗?

有两种方法(当然还有更多)

想象一下这种服务(如果是工厂也没关系):

使用此控制器:

app.controller('MainCtrl', function($scope, foo) {
  $scope.bar = foo.fn();
});
一种方法是使用您将使用的方法创建一个对象并监视它们:

foo = {
  fn: function() {}
};

spyOn(foo, 'fn').andReturn("Foo");
然后将该
foo
作为dep传递给控制器。不需要注入服务。那就行了

另一种方法是模拟服务并注入模拟的服务:

beforeEach(module('app', function($provide) {
  var foo = {
    fn: function() {}
  };
  
  spyOn(foo, 'fn').andReturn('Foo');
  $provide.value('foo', foo);
}));
当您注入时,然后
foo
它将注入这个

请看这里:

茉莉花2.0: 对于那些努力让答案奏效的人

从Jasmine 2.0开始,
andReturn()
变成了
和.returnValue()

因此,例如,在上述plunker的第一次测试中:

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');
  });

});
description('controller:MainCtrl',function(){
var-ctrl,foo,$scope;
在每个(模块(“应用”)之前;
beforeach(注入(函数($rootScope,$controller){
foo={
fn:function(){}
};

spyOn(foo,'fn').and.returnValue(“foo”);//您的
controller.js
语法是wrong@dcodesmith是的,我缩短了它,因为真正重要的是函数调用,忽略所有其他API服务我拒绝帮助你,除非你把那条严格的语句放在一个函数中:如果我只是想确保fn函数被调用一次呢?@Jackie the spy has
.calls.count()
你可以用它来验证它是1。