Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking global HTTP requests for all suites in Angular and Jasmine

In my app.config I am using a service called ui-router-extras FutureStates to dynamically create states from the results of a REST call. One of the side effects of this is that when my tests run, since I am loading my main app module in all of them, all tests make a call to that service and thus all tests fail with a

Error: Unexpected request: GET /api/v1/config
No more request expected

I can add the following to my test suites and it fixes the problem, registering this call with the backend so it expects it.

beforeEach(inject(function(_$httpBackend_){
    _$httpBackend_.whenGET(/\/api\/v1\/config.*/).respond([]);
}));

The issue is that this would need to be added to every test suite, which in my modular app is a lot of wet code. What I'm looking for is either a way to define this expectation globally once for all tests (either in a karma global file, or I'd even settle for a service/one-line import to place in my suites) or if my test setup or app.config is set up inefficiently a way to improve that.

What I've tried so far

// Defined in a tests-global.js file listed in my karma files array
beforeEach(inject(function(_$httpBackend_){
    _$httpBackend_.whenGET(/\/api\/v1\/req_params.*/).respond([]);
}));

which fails with Error: Injector already created, can not register a module! since in my individual test suites I am calling beforeEach(module('x')); to use that module's modules and you can't do that after an inject().

I've also tried

// Defined in a tests-global.js file listed in my karma files array
beforeEach(function() {
    var $injector = angular.injector(['ngMock']);
    $httpBackend = $injector.get('$httpBackend');
    $httpBackend.whenGET(/\/api\/v1\/req_params.*/).respond([]);
});

which produces no additional error, but also does not solve the Unexpected request issue.

Is there any way to handle expects for all tests, or if this is a sign that my testing structure is setup badly, a way to structure my code/tests better?

like image 620
DigTheDoug Avatar asked Nov 09 '22 15:11

DigTheDoug


1 Answers

As for me, I'm not including the main service module, but a mock for it, something like (as for me I'm including it inside karma.conf in "files"):

angular.module('some.service', []).service('MainService', function() {
    this.APP_HOST = 'localhost';
    this.APP_PORT = 8000;
});

Then, inside a test in a global beforeEach (remember that MainService is a mocked one, not a real):

beforeEach(inject(function(_$httpBackend_, MainService, $rootScope, $controller) {
    $httpBackend = _$httpBackend_;
    MainService.APP_HOST = 'localhost';
    MainService.APP_PORT = '8000';
    baseUrl = '//' + MainService.APP_HOST + ':' + MainService.APP_PORT;
    scope = $rootScope.$new();
    someCtrl = $controller('someCtrl', {
        $scope: scope,
        MainService: MainService
    });
}));

And will define HOW should it be mocked:

function mockHttpSuccessfulRequest() {
    $httpBackend
        .expectGET(baseUrl + '/api/surveys')
        .respond({
            surveys: [{
                something: false,
                date: '2015-03-11T08:28:58.765Z'
            }]
        });
}

So then you are defining this mock before a test suit:

beforeEach(mockHttpSuccessfulRequest);

And the you are free checking everything you want.

like image 140
Stan E Avatar answered Nov 15 '22 06:11

Stan E