单元测试 – 角度单元测试控制器 – 控制器内的嘲笑服务

我有以下情况:

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'

我也尝试过这样的东西,它没有工作:

describe('controllers',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',$timeout: timeout
        }
        );
    }));

    it('should have scope variable equals number',function() {
      spyOn(service,'APIService');
      scope.get_publisher_list();
      expect(scope.number).toBe(3);
    });
});

我该如何解决?有什么建议么?

有两种方式(或更确定)。

想像这样的服务(无论是工厂如何):

app.service('foo',function() {
  this.fn = function() {
    return "Foo";
  };
});

有了这个控制器:

app.controller('MainCtrl',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);
}));

当你注射时,它会注入这个。

看到这里:http://plnkr.co/edit/WvUIrtqMDvy1nMtCYAfo?p=preview

茉莉2.0:

对于那些努力使答案工作的人,

茉莉花2.0和Return()成为and.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');
  });

});

(资料来源:Rvandersteen)

相关文章

ANGULAR.JS:NG-SELECTANDNG-OPTIONSPS:其实看英文文档比看中...
AngularJS中使用Chart.js制折线图与饼图实例  Chart.js 是...
IE浏览器兼容性后续前言 继续尝试解决IE浏览器兼容性问题,...
Angular实现下拉菜单多选写这篇文章时,引用文章地址如下:h...
在AngularJS应用中集成科大讯飞语音输入功能前言 根据项目...
Angular数据更新不及时问题探讨前言 在修复控制角标正确变...