Angularjs $http请求未运行服务测试

Angularjs $http请求未运行服务测试,angularjs,testing,jasmine,Angularjs,Testing,Jasmine,我对服务对象进行了以下测试,承诺不会返回,http请求也不会从服务内部被调用,但它在浏览器测试中起作用 'use strict'; describe('Service: AuthService', function () { // load the controller's module beforeEach(module('adminPanelAngularApp')); var AuthService, AuthService, $rootScope; // Init

我对服务对象进行了以下测试,承诺不会返回,http请求也不会从服务内部被调用,但它在浏览器测试中起作用

'use strict';

describe('Service: AuthService', function () {

  // load the controller's module
  beforeEach(module('adminPanelAngularApp'));

  var AuthService, AuthService, $rootScope;

  // Initialize the controller and a mock scope
  beforeEach(inject(function (_AuthService_, _$rootScope_) {
    AuthService = _AuthService_;

    $rootScope = _$rootScope_;

  }));

  it('it auths', function () {
    AuthService.login(SOMECREDENTIALS).then(function(){
      console.log('this doesnt output in log');
    });

    expect(3).toBe(3);
  });
});
这是我的服务

angular.module('adminPanelAngularApp').factory('AuthService', ['$http', '$cookieStore', '$rootScope', '$location', '$q', function ($http, $cookieStore, $rootScope, $location, $q) {
  var authService = {};

  ....

  authService.get_current_user = function(){
    return $rootScope.current_user;
  }

  authService.login = function (credentials) {
    var url = REDACTED;

    return $http.post(server+url).then(function (res) {
      if (!res.data){
        return false;
      }

      if (res.data.error){
        $rootScope.login_error = res.data.error;
      }

      var user = {
        email: res.data.email,
        session: res.data.session,
        uid: res.data.uid
      }

      $cookieStore.put('loginData', user);
      $rootScope.current_user = user;

      return user;
    });
  };

...
我在考试中做错了什么

我知道我的代码也很糟糕,但如果我能测试这一点,我就成功了。

如果你不想模仿$http,我建议你使用$httpBackend

使用$httpBackend,您可以使用$http模拟调用

想象一下这项服务:

app.factory('Auth', function($http) {
  return {
    login: function() {
      return $http.post('/login');
    }
  };
});
我们的目标是测试您是否生成了$http.post,并且它是否成功返回,因此我们的想法如下:

describe('Service: Auth', function() {
  var Auth, $httpBackend;

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

    inject(function(_Auth_, _$httpBackend_) {
      Auth = _Auth_;

      $httpBackend = _$httpBackend_;

      $httpBackend.whenPOST('/login').respond(200);
    });
  });

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

  it('should do a proper login', function() {
    var foo;

    Auth.login().then(function() {
      foo = "success";
    });

    $httpBackend.flush();

    expect(foo).toBe("success");
  });

});
因此,对于初学者,我们注入了我们需要的Auth和$httpBackend

然后,我们称之为$httpBackend的whenPOST。基本上是这样的:

当有人发帖子/登录时,回复200

然后在测试中,我们调用login,它将执行$http.post。要处理这个$http.post,因为它是异步的,所以我们可以模拟真正的调用,使用$httpBackend.flush来处理调用

之后,我们可以验证.then是否已执行

那以后呢?在本例中,我们并不真正需要它,但当您想要断言调用是或是时,您可以将whenPOST更改为expectPOST,以使测试失败(如果从未发出该POST)。afterEach基本上是检查$httpBackend的状态,看看是否有任何期望不匹配

另一方面,您不需要手工创建承诺$http为您返回承诺,因此您可以直接返回$http调用,然后在$http上您可以:

这将稍微简化实现


演示

我想从真正的请求开始。从我最初的问题中删除承诺用法,因为我试图在不知道angular对后端做了什么的情况下强行通过结果。我想要一个解决方案,我可以使用一个真正的请求,直到我对我的规范感到满意,并将它们保存为模拟。不,这是不正确的。这是一个单元测试,意思是测试与世界其他地方隔离的工厂。永远不要在单元测试中执行真正的请求。这是完全错误的。事实上,angular mock有一些代码可以防止这种情况发生,但也有一些变通方法。我想做得不对,这样我就可以从测试套件中提取真实世界的响应并将其放入测试中,而不必使用postman或curl之类的其他方法。干杯
return user;