Angular - 单元测试一个在初始化时消耗承诺的控制器。 (茉莉花)

时间:2014-11-19 02:20:29

标签: angularjs unit-testing jasmine karma-runner

您有一个控制器ExampleController在初始化期间使用服务RequestService.data上的方法,您只想测试控制器(范围).property是否设置为响应中的值:

ExampleController:

app.controller('ExampleController'
            , ['$scope','RequestService', function($scope, RequestService){
  var ex = this;  
  (function initialize(){
    RequestService.
      data().
      then(function RSresp(info){
       ex.property = info.data.property;
      }
  })();
}]

RequestService:

app.service('RequestService', ['$http', function($http){
   this.data = function RSdata(){
     var closure = {prop: 'val', derp: 'aderp'};
     var url = 'http://aWebsite.' + closure.prop + '.com/' + closure.derp;
     return $http.get(url);
   }
}]);

单元测试:

describe('on initialization, ExampleController',function(){
 var controller, injector, $httpBackend, $scope, RequestService;

  beforeEach(function(){
   inject(function(_$injector_, _$controller_, _$rootScope_){
     injector = _$injector_;
     $scope = _$rootScope_.new();
     $httpBackend = injector.get('$httpBackend');
     controller = _$controller_('ExampleController', {$scope : $scope});
     RequestService = injector.get('RequestService');
   })
  })

  beforeEach(function(){
    $httpBackend.
       when('GET', 'http://aWebsite.val.com/aderp').
       respond({property: 'value'});
  });

  afterEach(function(){
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
  });

  it('has a property "property" with a value "value" ', function(){
    expect(controller.property).toBeDefined();
    expect(controller.property).toBe('value');
  });
});

我尝试了很多不同的东西,如:

expect($scope.property).toBeDefined();

spyOn(RequestService, 'data');
// or spyOn(RequestService, 'data').andCallThrough();
expect(controller.property).toBeDefined();
expect(RequestService.data).toHaveBeenCalled;

<3> Karma说:

"Error: Unflushed requests"

on initialization, ExampleController has a property "property" with a value "value" Fail: undefined is not defined.

console.log(controller)未显示该属性已设置,并且看起来似乎没有调用RequestService ...

我不知道。 我对RequestService的所有测试都在传递,而应用程序本身也可以工作......但我无法弄清楚如何编写规范来反映这一点。

我看过: Unit testing promises in controllers in AngularJS

和其他一些事实并非无关紧要......但没有运气

2 个答案:

答案 0 :(得分:3)

你的测试目前试图做得太多。

测试$http请求的责任应该是RequestService的测试。在测试调用RequestService的任何内容时,您会模拟RequestService

一般情况下,在单元测试中不要超过1依赖(因此,ExampleController - &gt; RequestService将是您的限制)。您的集成测试将负责测试整个序列。

所以你的单元测试应该是这样的:

describe('on initialization, ExampleController',function(){
 var $q, $controller, injector, $scope, RequestService;

  beforeEach(function(){
    inject(function(_$q_, _$injector_, _$controller_, _$rootScope_){
      $q = _$q_;
      injector = _$injector_;
      $controller = _$controller_;
      $scope = _$rootScope_.$new();
      RequestService = injector.get('RequestService');
    });
  });

  beforeEach(function(){
    spyOn(RequestService, 'data');
  });

  describe('with successful data retrieval', function () {
    beforeEach(function () {
      // mock a success
      RequestService.data.andReturn($q.when({property: 'value'}));
      controller = $controller('ExampleController', {$scope : $scope});

      $scope.$digest(); // fulfil the promises
    });

    it('has a property "property" with a value "value" ', function(){
      expect(controller.property).toBeDefined();
      expect(controller.property).toBe('value');
    });
  });

  describe('with failed data retrieval', function () {
    beforeEach(function () {
      // mock a fail
      RequestService.data.andReturn($q.reject(null));
      controller = $controller('ExampleController', {$scope : $scope});

      $scope.$digest(); // fulfill the promises
    });

    it('should do something', function(){
      expect('this').toBe('that');
    });
  });
});

答案 1 :(得分:0)

该问题的解决方案是调用$ digest。