Search code examples
angularjsjasminekarma-jasminehttpbackend

"Unsatisfied requests" when testing angularJS with Jasmine


I'm trying to write which tests if user uses right login/pass:

describe('LoginController', function () {
    beforeEach(angular.mock.module('task6'));

    var $rootScope, 
        $controller, 
        LoginService, 
        $httpBackend, 
        $resource, 
        $scope, 
        $controller;

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

    beforeEach(inject(function (_$rootScope_, 
                                _$controller_, 
                                _LoginService_, 
                                _$httpBackend_, 
                                _$resource_) {
        $rootScope = _$rootScope_;
        $controller = _$controller_;
        LoginService = _LoginService_;
        $httpBackend = _$httpBackend_;
        $resource = _$resource_;

        $scope = $rootScope.$new();
        controller = $controller('LoginController', {
                $scope: $scope
            });
    }));

    describe('LoginController.submitLogin', function () {

        var user = [
            {
                "login": "root",
                "password": "1234"
            }
        ];

        it('tries to login with right login/pass', function () {
            $httpBackend.expectGET(/users.json/)
                .respond(200, user);

            controller.loginField = 'John';
            controller.password = 'Smith';

            controller.submitLoginForm()
                .then(function () {
                    expect($rootScope.logged).toBe(false);
                })
                .catch(function () {
                    console.log.bind(console);
                });


            $httpBackend.flush();
        });

        it('tries to login with right login/pass', function () {

            $httpBackend.expectGET(/users.json/)
                .respond(200, user);

            controller.loginField = 'root';
            controller.password = '1234';

            controller.submitLoginForm()
                .then(function () {
                    expect($rootScope.logged).toBe(true);
                })
                .catch(function () {
                    console.log.bind(console);
                });
            $httpBackend.flush();
        });
    });
});

Here is the functions that I use in the test. In controller:

self.submitLoginForm = function() {
    return LoginService.signIn(self.loginField, self.password)
        .then(function() {
            if(!$rootScope.logged) {
                self.loginError = true;
            }
        })
        .catch(console.log.bind(console));
};

And in the service:

    var UsersResource = $resource('assets/data/users.json');

    function getUsers() {
        $httpBackend.expectGET(/users.json/);
        return UsersResource.query().$promise;

    }

    function signIn(loginField, password) {

        return getUsers()
            .then(function(users) {
                for (var i = 0; i < users.length; i++) {
                    if (users[i].login == loginField && users[i].password == password) {
                        $rootScope.logged = true;
                        $rootScope.user = users[i].login;
                        $location.path('/courses');
                        return true;
                    }
                }
                return false;
            })
            .catch(function () {
                console.log("Error: Users array wasn't retrieved from the server");
            });
    }

test works well until it ends successfully, otherwise it fails with an error:

Error: Unsatisfied requests: GET /users.json/

the first one points at the line 59 and line 13, the second one on the lines 77 and 13

Thank you!


Solution

  • So, the problem was in this function:

    function getUsers() {
        $httpBackend.expectGET(/users.json/);
        return UsersResource.query().$promise;
    }
    

    Since I'm expecting the request both in this function and in the test, it is expecting two requests and the second one is never made. $httpBackend.flush() notices this, and so $httpBackend.verifyNoOutstandingExpectation() does.