角单元测试控制器 - 内部控制嘲讽服务 [英] Angular unit-test controllers - mocking service inside controller

查看:117
本文介绍了角单元测试控制器 - 内部控制嘲讽服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下情况:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆