AngularJs:使用Jasmine测试服务

时间:2014-10-28 22:23:27

标签: angularjs jasmine karma-runner

我做了这个控制器

  app.controller('controller',['$scope','httpServices',function($scope,httpServices){
    $scope.items= undefined;

    httpServices.getItems( function(items){
        $scope.items= items;
    });
}]);

我写了这个测试

 describe('controller', function () {
        beforeEach(inject(function ($rootScope, $controller) {
            scope = $rootScope.$new();
            controller = $controller('controller', {
                '$scope': scope
            });
        }));
        it('defined', function () {
            expect(scope.items).toBeUndefined();
        })
    });

如何在调用服务后测试scope.items?

2 个答案:

答案 0 :(得分:0)

我认为您的服务httpServices正在发出一些http请求。因此,您应该使用mock-backend服务来测试您的控制器。

这样的事情,请注意我在代码中所做的评论:

describe('Your specs', function() {
  var $scope,
      $controller,
      $httpBackend;

  // Load the services's module
  beforeEach(module('yourApp'));

  beforeEach(inject(function(_$controller_, $rootScope, _$httpBackend_) {
    $scope = $rootScope.$new();
    $httpBackend = _$httpBackend_;
    $controller = _$controller_;

    //THIS LINE IS VERY IMPORTANT, HERE YOU HAVE TO MOCK THE RESPONSE FROM THE BACKEND 
    $httpBackend.when('GET', 'http://WHATEVER.COM/API/SOMETHING/').respond({});

    var createController = function(){
      $controller('controller', {$scope: $scope});
    }
  }));

  describe('Your controller', function() {  
    it('items should be undefined', function() {
      createController();
      expect(scope.items).toBeUndefined();
    });

    it('items should exist after getting the response from the server', function () {
        //THIS LINE IS ALSO VERY IMPORTANT, IT EMULATES THE RESPONSE FROM THE SERVER
        $httpBackend.flush();
        expect(scope.items).toBeDefined();
    });
  });
});

答案 1 :(得分:0)

问题标题声明这是测试服务,但问题的代码看起来像是试图测试控制器。这个答案描述了如何测试控制器。


如果您正在测试调用httpServices.getItems的控制器,那么您需要模拟它/ stub getItems以便

  • 在测试中控制它
  • 不假设真实httpServices.getItems的任何行为。毕竟,您正在测试控制器,而不是服务。

执行此操作的方法是在beforeEach块(在创建控制器之前调用)提供getItems的伪实现,只保存传递给它的回调。

var callback;
beforeEach(inject(function(httpServices) {
  callback = null;
  spyOn(httpServices, 'getItems').and.callFake(function(_callback_) {
    callback = _callback_;
  });
});

在测试中,您可以调用此回调,传入一些虚假数据,并测试是否已在范围内正确设置。

it('saves the items passed to the callback on the scope', function () {
  var testItems = {};
  callback(testItems);
  expect($scope.items).toBe(testItems);
});

可以看到http://plnkr.co/edit/Z7N6pZjCS9ojs9PZFD04?p=preview


如果您确实想要测试httpServices.getItems本身,那么就可以进行单独的测试。假设getItems调用$http,那么您最有可能需要使用$httpBackend来处理模拟响应。最有可能的是,这些测试不会实例化任何控制器,我怀疑不需要在任何范围内做任何事情。