单元测试使用承诺的角度控制器和服务?

时间:2016-10-18 14:27:28

标签: angularjs unit-testing asynchronous jasmine karma-jasmine

我无法让测试结果通过我使用非常基本的实现来更深入地理解测试。

我有一个工厂,它返回一个承诺,从我的控制器访问。我想测试调用成功并将响应分配给repos var。以下是代码:

'use strict';

angular.module('app')
  .factory('searchServ', function ($timeout, $q, $http) {
    return {
      fetch: function(user) {
        var deferred = $q.defer();

        $timeout(function(){
          $http({method: 'GET', url: 'https://api.github.com/users/' + user + '/repos'}).then(function(repos) {
            deferred.resolve(repos.data);
          }, function(reason){
            deferred.reject(reason.status);
            console.log(reason);
          });
        }, 30);

        return deferred.promise;
      }
    };
  })
  .controller('MainCtrl', function ($scope, searchServ) {
    $scope.results = function(user) {
      $scope.message = '';
      searchServ.fetch(user).then(function (repos) {
        if(repos.length){
          $scope.message = '';
          $scope.repos = repos;
        }
        else{
          $scope.message = 'not found'
        }
      }, function (){
        $scope.message = 'not found';
      });
    };
  });

//Test

'use strict';

describe('MainCtrl', function () {
  var scope, searchServ, controller, deferred, repos = [{name: 'test'}];
  // load the controller's module
  beforeEach(module('app'));

  beforeEach(inject(function($controller, $rootScope, $q) {
    searchServ = {
      fetch: function () {
        deferred = $q.defer();
        return deferred.promise;
      }
    };
    spyOn(searchServ, 'fetch').andCallThrough();
    scope = $rootScope.$new();
    controller = $controller('MainCtrl', {
      $scope: scope,
      fetchGithub: fetchGithub
    });


  }));
  it('should test', function () {
    expect(scope.test).toEqual('ha');
  });

  it('should bind to scope', function () {
    scope.results();
    scope.$digest();
    expect(scope.message).toEqual('');
    //expect(scope.repos).not.toBe(undefined);
  });
});

运行测试会出现以下错误:

  

TypeError: undefined is not a function (evaluating 'spyOn(searchServ, 'fetch').andCallThrough()') in test/spec/controllers/main.js (line 15)

我知道如何测试它,以便它测试范围绑定以及异步调用吗?

1 个答案:

答案 0 :(得分:2)

您的代码存在很多问题。

我已为此目的创建 this Plunkr index.js是包含您的代码和测试用例的文件。我根据惯例和最佳实践编辑了大部分内容。

我想给你一些指示:

  • 由于$http返回一个承诺,您应该使用它,而不是解析承诺并从您的方法创建另一个承诺。不确定为什么超时使用。因此,我从$q的依赖项中删除了$timeoutsearchServ
  • 我在测试用例中删除了您使用的deferred变量。
  • 您应该使用angular-mocks.js来模拟您的服务和其他依赖项,而不是在您的测试用例中定义服务(您的方式。)
  • 您应该创建单独的describe块来测试代码的不同部分(在这种情况下为controller)。

希望这有帮助!