Skip to content Skip to sidebar Skip to footer

Angularjs Unit Test With $http Request Never Fires .then() Callbacks

I'm trying to get unit tests running with mocked responses in separate json files. The tests were working when I used $q to return promises resolved manually in my OpsService, but

Solution 1:

The first thing is that each asserted request should be mocked request. The requests should be flushed with $httpBackend.flush(), it triggers a digest, $rootScope.$apply() and $rootScope.$digest() (they duplicate each other) shouldn't be called.

The second thing is that it shouldn't be done in controller spec! Controller is a separate unit that depends on a service, it should be tested in isolation with mocked service. OpsService is a different unit.

it('should retrieve big ten data', inject(function () {
    $httpBackend.expect('GET', '/jsonMocks/api/big-ten.json').respond(200, ...);
    $httpBackend.expect('GET', '/jsonMocks/api/dashboard-data.json').respond(200, ...);

    OpsService.get.bigTen().then(function (result) {
       expect(result)...
    }, function (err) {
       throw err;
    });
    OpsService.get.dashboardData()...

    $httpBackend.flush();
}));

it('should test a controller', inject(function () {
    var OpsServiceMock = { get: {
       bigTen: jasmine.createSpy().and.returnValue(...),
       dashboardData: jasmine.createSpy().and.returnValue(...)
    } };

    $scope = $rootScope.$new();

    var ctrl = $controller('HomeController', {
        $scope : $scope,
        OpsService : OpsServiceMock 
    });

    $rootScope.$digest();

    expect(OpsServiceMock.get.bigTen).toHaveBeenCalled();
    expect(OpsServiceMock.get.dashboardData).toHaveBeenCalled();
    expect...
}));

Solution 2:

EDIT: Looking at the documentation for $httpBackend, the expect and when methods don't work together. They're different options for setting up the backend.

expect looks like it adds an expectation that the call will happen, and gives you a .respond() you call call on the result to give what to respond with.

when just lets you set up a response for a particular response without actually saying you expect it.

So in your tests the expect calls are overwriting the when definition you did, and don't return any response because you didn't configure one.

So, I think you can just get rid of the expects and put a flush after your controller like so:

it('should retrieve big ten data', inject(function () {
    // Controller Setupvar ctrl = createController();

    $httpBackend.flush();

    // Initialize$rootScope.$apply();
    $rootScope.$digest();

    expect(ctrl.topMetrics.display.messages.count).toEqual(745);
}));

Or change your whens in the beforeEach to expects and then you probably won't need the flush.

Post a Comment for "Angularjs Unit Test With $http Request Never Fires .then() Callbacks"