4
votes

I have AngularJS app with unit tests covering it. I added one more http request in .run part of application which checking user authentication. Now about 60% of my tests fails because they found 'unexpected http request'. Even directives tests are fail. How can I avoid running this request in tests? How can I easily mock this request in all tests? Im trying to not to put httpBackend.expect('GET', 'URL') to each test - that's too much work.

Testing with Jasmine + Karma

Thanks. I can give more details if needed.

2
What test framework do you use? jasmine?Tim
yes. Forgot to mention. Updated the questionFyodor Khruschov

2 Answers

2
votes

There are a few ways to do this:

1.) Include a beforeEach that Tim Castelijns suggested but for every spec file
2.) Include the beforeEach in a separate file called app-mocks.js & include in your karma.conf.js (I'm guessing you have one).

karma.conf.js

files: [
    'location/of/app-mocks.js',
    'src/app/**/*.js'
],

app-mocks.js

(function () {
    'use strict';

    beforeEach(inject(function ($httpBackend) {
        $httpBackend.whenGET('blahblahblah.com/cat/:id/food').respond('');
    }));
})();

3.) Separate out user authentication logic from the core app and create an $http wrapper service (suggested). Thus you could have (simplified example):

app.js

angular.module('myApp', ['myApp.services']);

user-service.js

angular.module('myApp.services', [])
    .factory('User', function ($http) {
        function authenticate() {
            // authenticate user
        }

        return {
            authenticate: authenticate
        };
    });

and same for your directives, controllers, etc. This way, you can unit test all of your components in isolation without having to worry about intertwined logic that is actually specific to one type of functionality. Also, when you do test core app functionality, you can just mock or spy on your User service. In your spec files you would inject only the module & functionality you are testing. So instead of injecting your entire core app module, you would:

To test services

beforeEach(module('myApp.services'));

To test directives

beforeEach(module('myApp.directives'));

etc.

Of Note: When your application starts to get big, I would consider organizing your app components based on feature rather than by type as this example above does.

0
votes

You can use a beforeEach block to define a call that all tests should expect

var httpBackend;
beforeEach(inject(function(_$httpBackend_) {
  httpBackend = _$httpBackend_;
  httpBackend.expect('GET', 'URL').respond('');
}

Note the .respond('') I added, an expect call needs this, see the documentation if you want to know why.

This beforeEach functionality comes with the widely used jasmine testing framework.