Search code examples
javascriptangularjsunit-testingjasminehttpbackend

Make $httpBackend ignore any requests made to server


I have the following controller (notice that at instantiation time I make an explicit call to $scope.getNotifications()):

bla.controller("myctrl", [
    "$scope", "$http", "configs", function ($scope, $http, configs) {

        $scope.getNotifications = function () {
            $http.get("bla/blabla").success(function (data) {

            });
        };

        $scope.removeNotification = function (notification) {
            var index = $scope.allNotifications.indexOf(notification);
            $scope.allNotifications.splice(index, 1);
        };

        $scope.getNotifications();
    }
]);

Then I make some unit tests (notice that the controller gets instantiated in the before each):

describe("blaController", function () {

    var scope, $httpBackend;

    beforeEach(module('bla'));

    beforeEach(inject(function ($controller, $rootScope, _$httpBackend_) {
        scope = $rootScope.$new();
        $httpBackend = _$httpBackend_;
        $controller('blaCtrl', { $scope: scope });
    }));

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

 it("should get all notifications from server when instantiated", function () {
    //arrange
    $httpBackend.expectGET("api/v1/notifications").respond(200, {});
    $httpBackend.flush();

    //act - done implicitly when controller is instantiated  
});

it("should store all notifications from server on the client when success call to server", function () {
    //arrange
    $httpBackend.whenGET("api/v1/notifications").respond(200, [{ a: 1, b: 2 }, { c: 3, d: 4 }]);
    $httpBackend.flush();

    //act - done implicitly when controller is instantiated

    //assert
    expect(scope.allNotifications).toEqual([{ a: 1, b: 2 }, { c: 3, d: 4 }]);
});

Everything is fine until now. All tests pass. But when I add a new test (see bellow) that does not require any HTTP calls it fails because in the afterEach() it verifies for expecations but there are no expectations set in the removeNotification(). This is the error message from karma: PhantomJS 1.9.7 (Windows 8) notificationCenterController removeNotification should remove the given notification from th e list FAILED Error: Unexpected request: GET api/v1/notifications No more request expected

it("should remove the given notification from the list", function () {
            //arrange
            var targetObj = { a: 2 };
            scope.allNotifications = [{ a: 1 }, targetObj, { a: 3 }];

            //act
            scope.removeNotification(targetObj);

            //assert
            expect(scope.allNotifications).toEqual([{ a: 1 }, { a: 3 }]);
        });

Most of my test do have http calls so placing the verify in the afterEach makes sense. I was wondering what other option do I have to avoid copy pasting the afterEach body in N-1 tests. Is there a way to tell $httpBackend to ignore any calls?


Solution

  • you can wrap your test in describe block like below.

    describe("blaController", function () {
    
        var scope, $httpBackend;
    
        beforeEach(module('bla'));
    
        beforeEach(inject(function ($controller, $rootScope, _$httpBackend_) {
            scope = $rootScope.$new();
            $httpBackend = _$httpBackend_;
            $controller('blaCtrl', { $scope: scope });
        }));
    
        describe('test http calls', function() {
    
            afterEach(function(){
                //assert
                $httpBackend.verifyNoOutstandingExpectation();
                $httpBackend.verifyNoOutstandingRequest();
            });
    
            it("should get all notifications from server when instantiated", function () {
                //arrange
                $httpBackend.expectGET("api/v1/notifications").respond(200, {});
                $httpBackend.flush();
    
                //act - done implicitly when controller is instantiated  
            });
    
            it("should store all notifications from server on the client when success call to server", function () {
            //arrange
                $httpBackend.whenGET("api/v1/notifications").respond(200, [{ a: 1, b: 2 }, { c: 3, d: 4 }]);
                $httpBackend.flush();
    
                //act - done implicitly when controller is instantiated
    
                //assert
                expect(scope.allNotifications).toEqual([{ a: 1, b: 2 }, { c: 3, d: 4 }]);
            });
    
        }); 
    
        describe('other tests', function(){
            it("should remove the given notification from the list", function () {
                //arrange
                var targetObj = { a: 2 };
                scope.allNotifications = [{ a: 1 }, targetObj, { a: 3 }];
    
                //act
                scope.removeNotification(targetObj);
    
                //assert
                expect(scope.allNotifications).toEqual([{ a: 1 }, { a: 3 }]);
            });
        });
    });