【问题标题】:AngularJS+Jasmine: $httpBackend not working as expectedAngularJS+Jasmine:$httpBackend 没有按预期工作
【发布时间】:2014-03-01 21:52:50
【问题描述】:

我正在使用 JasmineKarma 来测试我基于 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
            });

        });
    });
});

假设 GITHUB_API_URL 等于 'https://api.github.com/' 并且 GITHUB_USER 等于 'wilk'

我正在使用 Karma-Jasmine 0.1.5AngularJS 1.2.6(使用 Angular Mocks 和 Scenario 1.2.6)运行此测试。

这段代码有什么问题?

【问题讨论】:

  • 我用你的代码创建了一个Plunker script,但我不知道 GITHUB_USER 是什么。你介意更新一下吗?
  • @MichaelBenford 这是一个常数,正如我提到的,它等于字符串 'wilk'。
  • 我的错。没注意。

标签: angularjs unit-testing service jasmine karma-runner


【解决方案1】:

让我们分别谈谈每个错误:

错误:没有待处理的刷新请求!

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

错误:未满足的请求:GET https://api.github.com/users/wilk

原因同上。由于服务未使用$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);
        });
    });
});

Plunker

注意:我已经稍微改变了注入东西的方式,但是你做的方式很好,只要你先创建$httpBackend

【讨论】:

  • 哇! +1 的好答案!清晰详细!感谢您的解释!但是我还不明白“注入”功能是如何工作的。如何注入这些重命名的参数?我的意思是,它怎么知道 UserService 它是我模块的服务?
  • @Wilk 当您调用module('myApp') 时,Angular 会加载该模块包含的所有服务,以便注入器可以使用其中的任何一个。参数名称中的下划线只是为了防止变量名称发生冲突。 Angular 只是忽略它们。但是,如果您的局部变量具有不同的名称,则不需要使用它们。有关here的更多信息。
  • 非常感谢,如果我能一次又一次地 +1,我会的。我竭力想弄清楚为什么我的要求没有得到满足。
  • 我希望我能再次投票,几个月前我在这里是因为第一个错误,现在我又找到了第二个错误答案哈哈。再次感谢。
  • ummmm,你能详细说明“你创造的期望永远不会实现”吗?我收到Error: Unsatisfied requests: PUT /api/v1/categories/by_key/zoom 错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-14
  • 2016-09-25
  • 2015-09-22
相关资源
最近更新 更多