AngularJS+;Jasmine:$httpBackend未按预期工作

AngularJS+;Jasmine:$httpBackend未按预期工作,angularjs,unit-testing,service,jasmine,karma-runner,Angularjs,Unit Testing,Service,Jasmine,Karma Runner,我正在使用Jasmine和Karma来测试我基于Angular构建的应用程序 我必须测试一个加载用户数据的服务,并使用$httpBackend模拟响应。 但是,当我运行测试时,出现了两个错误: 错误:没有挂起的刷新请求 错误:未满足的请求:获取 模块: 'use strict'; app.service ('UserService', ['$resource', '$q', 'GITHUB_API_URL', function ($resource, $q, GITHUB_API_URL)

我正在使用Jasmine和Karma来测试我基于Angular构建的应用程序

我必须测试一个加载用户数据的服务,并使用$httpBackend模拟响应。 但是,当我运行测试时,出现了两个错误:

  • 错误:没有挂起的刷新请求
  • 错误:未满足的请求:获取
模块:

'use strict';

app.service ('UserService', ['$resource', '$q', 'GITHUB_API_URL', function ($resource, $q, GITHUB_API_URL) {
  var userResource = $resource (GITHUB_API_URL + '/users/:user', {user: '@user'}) ,
      userModel = {};

  return {
    data: function () {
        return userModel;
    } ,
    populate: function (user) {
      var deferred = $q.defer () ,
          userRequest = userResource.get ({user: user});

      $q
          .when (userRequest.$promise)
          .then (function (data) {
              userModel = data;
              deferred.resolve (data);
          });

      return deferred.promise;
    }
  };
}]);
'use strict';

describe ('Service: UserService', function () {
    beforeEach (module ('myApp'));

    var $appInjector = angular.injector (['myApp']) ,
        UserService = $appInjector.get ('UserService') ,
        GITHUB_API_URL = $appInjector.get ('GITHUB_API_URL') ,
        GITHUB_USER = $appInjector.get ('GITHUB_USER') ,
        $httpBackend;

    beforeEach (inject (function ($injector) {
        $httpBackend = $injector.get ('$httpBackend');

        $httpBackend
            .when ('GET', GITHUB_API_URL + '/users/' + GITHUB_USER)
            .respond ({
                login: GITHUB_USER ,
                id: 618009
            });
    }));

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

    describe ('when populate method is called', function () {
        it ('should returns user data', function () {
            $httpBackend.expectGET (GITHUB_API_URL + '/users/' + GITHUB_USER);

            UserService.populate (GITHUB_USER);
            $httpBackend.flush ();
            expect(UserService.data ()).toEqual ({
                login: GITHUB_USER ,
                id: 618009
            });

        });
    });
});
测试:

'use strict';

app.service ('UserService', ['$resource', '$q', 'GITHUB_API_URL', function ($resource, $q, GITHUB_API_URL) {
  var userResource = $resource (GITHUB_API_URL + '/users/:user', {user: '@user'}) ,
      userModel = {};

  return {
    data: function () {
        return userModel;
    } ,
    populate: function (user) {
      var deferred = $q.defer () ,
          userRequest = userResource.get ({user: user});

      $q
          .when (userRequest.$promise)
          .then (function (data) {
              userModel = data;
              deferred.resolve (data);
          });

      return deferred.promise;
    }
  };
}]);
'use strict';

describe ('Service: UserService', function () {
    beforeEach (module ('myApp'));

    var $appInjector = angular.injector (['myApp']) ,
        UserService = $appInjector.get ('UserService') ,
        GITHUB_API_URL = $appInjector.get ('GITHUB_API_URL') ,
        GITHUB_USER = $appInjector.get ('GITHUB_USER') ,
        $httpBackend;

    beforeEach (inject (function ($injector) {
        $httpBackend = $injector.get ('$httpBackend');

        $httpBackend
            .when ('GET', GITHUB_API_URL + '/users/' + GITHUB_USER)
            .respond ({
                login: GITHUB_USER ,
                id: 618009
            });
    }));

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

    describe ('when populate method is called', function () {
        it ('should returns user data', function () {
            $httpBackend.expectGET (GITHUB_API_URL + '/users/' + GITHUB_USER);

            UserService.populate (GITHUB_USER);
            $httpBackend.flush ();
            expect(UserService.data ()).toEqual ({
                login: GITHUB_USER ,
                id: 618009
            });

        });
    });
});
假设GITHUB\u API\u URL等于“”,GITHUB\u USER等于“wilk”

我使用Karma Jasmine 0.1.5AngularJS 1.2.6运行此测试(使用角度模拟和场景1.2.6)


此代码有什么问题?

让我们分别讨论每个错误:

错误:没有挂起的刷新请求

发生这种情况的原因是没有通过
$httpBackend
发出请求,因此没有需要刷新的内容。这是因为您在
$httpBackend
之前实例化了
UserService
,因此Angular不知道它应该使用它而不是真正的
$http
。如果您查看控制台,您将看到正在发送一个真正的请求

错误:未满足的请求:获取

原因同上。由于服务未使用
$httpBackend
,因此您所创建的期望永远无法实现

以下是在考虑了以上所有因素后重构的规范:

describe ('Service: UserService', function () {
    var UserService,
        GITHUB_API_URL,
        GITHUB_USER,
        $httpBackend;

    beforeEach(function() {
      module('plunker');

      inject(function( _$httpBackend_, _UserService_, _GITHUB_API_URL_, _GITHUB_USER_) {
        $httpBackend = _$httpBackend_;
        UserService = _UserService_;
        GITHUB_API_URL = _GITHUB_API_URL_;
        GITHUB_USER = _GITHUB_USER_;
      });
    });

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

    describe ('when populate method is called', function () {
        it ('should returns user data', function () {
            $httpBackend
              .whenGET(GITHUB_API_URL + '/users/' + GITHUB_USER)
              .respond ({
                  login: GITHUB_USER,
                  id: 618009
              }); 

            UserService.populate(GITHUB_USER);
            $httpBackend.flush();

            expect(UserService.data().login).toBe(GITHUB_USER);
            expect(UserService.data().id).toBe(618009);
        });
    });
});


注意:我已经稍微改变了注入的方式,但只要您先创建
$httpBackend

我用您的代码创建了一个,但我不知道GITHUB\u用户是什么。你介意更新它吗?@MichaelBenford它是一个常量,正如我提到的,它等于字符串“wilk”。我的错。没注意到,哇+1为伟大的答案!清晰而详细!谢谢你的解释!然而,我还不明白“注入”函数是如何工作的。如何注入这些重命名的参数?我的意思是,它怎么知道UserService是我模块的服务?@Wilk当你调用
module('myApp')
Angular加载模块包含的所有服务,以便注入器可以使用它们中的任何一个。参数名称中的下划线只是为了防止变量名称冲突。我只是不理他们。但是,如果局部变量有不同的名称,则不需要使用它们。更多关于这方面的信息。非常感谢,如果我能一次又一次地+1这个,我会的。我在绞尽脑汁想弄清楚为什么我的请求没有得到满足。我希望我能再次投票,几个月前我在这里犯了第一个错误,现在我又在第二个错误中找到了答案。再次感谢。嗯,你能详细说明一下“你创造的期望永远不会实现”吗?我收到
错误:未满足的请求:PUT/api/v1/categories/by_key/zoom
错误