Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using $httpBackend in a service whilst testing an Angular controller

I'm trying to test a controller in my Angular framework:

.controller('UserCtrl', ['$scope', '$location', 'User', 'Config',
    function ($scope, $location, User, Config) {
       ...
    }])

This controller depends on a couple of Services that require the $http object to make server calls:

.factory('User', ['$http', function ($http) {
    var data = {};

    return {
        query: function(oper, putdata, callback){
            if(oper == 'get'){
            $http.get(getUrl("user",null)).success(function(data2) {
                console.log(data2);

                callback(data2);
                data.userinfo = data2;
            });
            },

        userinfo: data
    };
}])

But when I try bootstrapping the controller I can't get httpBackend to work:

describe('UserCtrl', function(){

    var ctrlScope, ctrl, $httpBackend, controllerService;

    beforeEach(
        inject(function($httpBackend, $http, $rootScope, $controller, User, Config) {
            _User = User;
            _Config = Config;
            spyOn(User, 'getUserInfo').andCallThrough();
            //spyOn(User, 'query').andCallThrough();

            ctrlScope = $rootScope.$new();
            controllerService = $controller;
            httpMock = $httpBackend;

        })
    );

    it('should create setup userinfo object ', function() {
        httpMock.expectGET("/user/default/details").
            respond({somejson});

        ctrl = controllerService('UserCtrl', {$scope: ctrlScope, $location: location, User: _User, Config: _Config});
        expect(_User.getUserInfo).toHaveBeenCalled();
        httpMock.flush();
        expect(ctrlScope.userinfo.length).toBe(1);

    });
});

All I ever get is:

Error: No pending request to flush !

so is it possible to use httpBackend with a service that you have called from a controller you are testing?

like image 686
magicaltrout Avatar asked May 29 '13 09:05

magicaltrout


1 Answers

Is there a reason you want to specifically test for a GET request? This is an implementation detail of your User service.

Regardless of whether your function is called query() or getUserInfo(), I suspect all that you really want to know is that the function was called on your User service. It's up to the User service to have it's own set of tests that will test that a GET request was made to /user/defaults/details.

The reasoning behind this is that you don't want unrelated unit tests to break when you change the implementation of your User service. What happens when your API changes to /user/query? Your UserCtrl tests should not break, nor should any other controller that's using User service. If your UserCtrl is calling getUserInfo() on User service, it's doing the right thing as far as you're concerned. Your User service unit tests will break and once you fix them to point to your new URL, everything is back in order.

like image 175
achan Avatar answered Oct 17 '22 03:10

achan