简体   繁体   中英

Angular unit test factory that uses http request

I am working on an angular js app with karma/Jasmine testing framework, I need to test a factory that returns a http promise but it always return undefined

here is my factory

 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; } } }]) 

here is my tests

Update thanks to your answers I modified my code to the following but no I got this error

Possibly unhandled rejection: {"status":0,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":" https://api.github.com/users?since=1 ","headers":{"Accept":"application/json, text/plain, / "},"cached":false},"statusText":""} thrown

 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(); }) }) 

Thanks in advance!

I think you need to pass a function that returns a array with 3 items in it, to whenGET(). respond ().

Maybe, you can try something like this:

 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();
...

(I prefer to arrange spec outside of it() clause for better readability)

You're missing a $httpBackend.flush(); call after your test method call. It will invoke a success/error or then part and resolve a $q's promise properly. For more tests I would move a $httpBackend.whenGET to each test case separately so I can later verify it per use case but it's just my personal opinion.

I find it a little suspicious that you mix a $controller and a factory in one test. I would suggest to split them, and in controller test just check the calls to service methods and in a facotry test itself do a $httpBackend stuff.

Below I paste your test with my corrections. It works now for me:

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();
});

Important notices: 1)afterEach - check if no pending requests remain after your call 2) your url differ with a parameter ?since=1. But you do not give it as a parameter in your code so i do not understand why you added this parameter. Maybe consider string concatenation with url and parameter ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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