使用HTTP请求的Angular单元测试工厂



我正在使用Karma/Jasmine测试框架上的Angular JS应用程序,我需要测试一个返回HTTP Promise的工厂,但它总是返回未定义的

这是我的工厂

angular.module('GithubUsers').factory('Users',['$http','$q',function($http,$q){
  return{
    getAllUsers:function(){
      var defered= $q.defer();
      $http({
        url:'https://api.github.com/users',
        method:'GET'
      }).then(function(users){
        defered.resolve(users.data);
      },function(err){
        defered.reject(err);
      })
      return defered.promise;
    }
  }
}])

这是我的测试

update 多亏了您的答案,我将代码修改为以下内容,但不,我有此错误

可能是没有指责的拒绝:{"状态":0," config":{"方法":" get"," transformRequest":[null]," transformResponse":[null]," jsonpcallbackparam":" callback":" callback"," url":" https://api.github.com/users?since = 1","标题":{" cackect":" application/json,text/plain/plain,/"}," cached":false}," statustext":"}投掷

describe('Test Users Factory',function(){
  var $controller,
  Users,
  $rootScope,
  $httpBackend,
  $q;
  beforeEach(module('GithubUsers'));
  beforeEach(inject(function(_$controller_,_Users_,_$rootScope_,_$httpBackend_,_$q_){
    $controller = _$controller_;
    Users = _Users_;
    $rootScope= _$rootScope_;
    $httpBackend=_$httpBackend_;
    
   
  }))
  
  it('should get users',function(){
   
    var result;
    $httpBackend.whenGET('https://api.github.com/users?since=1').respond(function(){
       return {data:[{id:2}],status:200};
    })
    Users.getAllUsers().then(function(res){
      result = res;
    });
    $httpBackend.flush();
    $rootScope.$digest()
    expect(result).toBeTruthy();
  })
})

预先感谢!

我认为您需要传递一个函数,该函数在其中返回一个带有3个项目的数组,to wherget()。)。

也许,您可以尝试这样的事情:

 beforeEach(angular.mock.inject(function (User, $httpBackend, $http) {
    ...
    this.withOKUsers = function() {
            var i1 = new User();
            i1.id = 10;
            return [200, JSON.stringify([ i1]), {}];
    } ...
}));
...    
it('should get users',function(){
$httpBackend
    .whenGET('https://api.github.com/users')
    .respond(this.withOKUsers);
Users.getAllUsers().then(function(res){
  result = res;
});    
$httpBackend.flush(); 
expect(result).not.toBeNull();
...

(我更喜欢在IT()子句之外安排规格以获得更好的可读性)

您缺少 $ httpbackend.flush(); 在测试方法调用后调用。它将调用成功/错误,或者分散并正确解决$ Q的诺言。有关更多测试,我将分别移动$ httpbackend.thenget到每个测试案例,以便以后每个用例验证它,但这只是我的个人意见。

我发现您将$控制器和工厂混合在一个测试中有点怀疑。我建议将它们拆分,在控制器测试中,只需检查到服务方法的调用,然后在Facotry测试中本身就可以做$ HTTPBACKEND的东西。

下面我用更正粘贴了您的测试。现在对我有用:

describe('Test Users Factory', function () {
var Users,
$rootScope,
$httpBackend,
$q;
beforeEach(module('app.utils'));
beforeEach(inject(function (_Users_, _$rootScope_, _$httpBackend_, _$q_) {
    Users = _Users_;
    $rootScope = _$rootScope_;
    $httpBackend = _$httpBackend_;
}));
afterEach(function () {
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
});
it('should get users', function () {
    var result;
    $httpBackend.when('GET', "https://api.github.com/users").respond({ data: [{ id: 2 }], status: 200 });
    Users.getAllUsers().then(function (res) {
        result = res;
        expect(result).toBeTruthy();
    });

    $httpBackend.flush();
    $rootScope.$digest();
});

重要通知:1)Aftereach-检查您的电话后是否没有保留待处理的请求2)您的URL因参数而异?因为= 1。但是您不会将其作为代码中的参数,因此我不明白为什么添加此参数。也许考虑使用URL和参数的字符串串联?

最新更新