简体   繁体   English

带有$ rootScope和$ httpBackend的Angularjs单元测试

[英]Angularjs unit test with $rootScope and $httpBackend

I have a service which fires a HTTP request. 我有一个可以触发HTTP请求的服务。 This request makes use of the $rootScope.config object (there is my base url stored), but for some reason when I use $httpBackend, $rootScope is not loaded correct. 该请求利用了$ rootScope.config对象(存储了我的基本URL),但是由于某些原因,当我使用$ httpBackend时,没有正确加载$ rootScope。

Service: 服务:

myAppServices.factory('Auth', function($rootScope, $http, $cookieStore){   
  return {
    logout: function(success, error) {
      $http.get($rootScope.config.apiUrl + '/users/logout').then(function(response){
      }, function(response) {
      });
    }

Test: 测试:

describe('services', function() {
  var Auth;
  var $httpBackend;
  var $cookieStore;
  var $rootScope;

  beforeEach(function() {
    module('myApp.services');
  });

  beforeEach(inject(function($injector) {
    $httpBackend = $injector.get('$httpBackend');
    $cookieStore = $injector.get('$cookieStore');
    $rootScope = $injector.get('$rootScope');
    Helper = $injector.get('Helper');
    Auth = $injector.get('Auth');
  }));

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

describe('logout', function() {
  it('should make a request and invoke callback', function() {
    // I try to set $rootScope here, works in my other tests, but not in this test
    $rootScope = { config: { apiUrl: 'foo' } };

    var invoked = false;
    var success = function() {
      invoked = true;
    };
    var error = function() {};

    $httpBackend.expectPOST('/logout').respond();
    Auth.logout(success, error);
    $httpBackend.flush();
    $rootScope = { config: { apiUrl: 'foo' } };
    expect(invoked).toEqual(true);

It normally works when I set $rootScope in my test to some value, but not in this test. 当我在测试中将$ rootScope设置为某个值但在此测试中未将其设置为正常时,它通常可以工作。

Why is it that $rootScope does not have the config attribute in my service, when using $httpBackend? 使用$ httpBackend时,为什么$ rootScope在我的服务中没有config属性?

The problem: 问题:

There are two different things with the same name that cause confusion: 具有相同名称的两种不同事物会引起混淆:

  • There is the $rootScope (the actual $rootScope that is the ancestor of all Scopes and is injected through Angular's Dependency Injection). 有一个$rootScope (实际的$rootScope是所有Scope的祖先,并通过Angular的Dependency Injection注入)。
  • And there is a local variable named $rootScope that you declare in your test-suite. 在测试套件中声明了一个名为$rootScope的局部变量。

For the sake of clarity, I will refer to the latter as $rootScope{var} . 为了清楚起见,我将后者称为$rootScope{var}


Here is what's going on: 这是怎么回事:

  1. At some point $rootScope will be injected into your service's constructor (to be used later on when making the $http request). 在某个时候, $rootScope将注入到服务的构造函数中(稍后在发出$http请求时使用)。

  2. $rootScope{var} is initialized to the value returned by $injector.get('$rootScope'); $rootScope{var}初始化为$injector.get('$rootScope');返回的值$injector.get('$rootScope'); .
    At this point $rootScope and $rootScope{var} are the same object. 此时, $rootScope$rootScope{var}同一对象。

  3. This line: $rootScope = { config: { apiUrl: 'foo' } }; 这行代码: $rootScope = { config: { apiUrl: 'foo' } }; creates a new object and assigns it as the value of $rootScope{var} . 创建一个对象,并将其分配为$rootScope{var}的值。
    At this point $rootScope and $rootScope{var} are not the same object any more. 此时, $rootScope$rootScope{var} 不再是同一对象。

  4. $rootScope{var} does have a config property, but your service is going to use $rootScope , which knows nothing about config . $rootScope{var}确实具有config属性, 但是您的服务将使用$rootScope ,它对config一无所知。


The solution: 解决方案:

In order to add the config property to the actual $rootScope change your code like this: 为了将config属性添加到实际的$rootScope更改您的代码,如下所示:

$rootScope.config = { apiUrl: 'foo' };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM