4

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? Commented Jun 11, 2014 at 8:56
  • yes. Forgot to mention. Updated the question Commented Jun 11, 2014 at 9:20

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

4 Comments

thanks. This is good solution, but I have about 10 (it's just a start of a project) test files. And I know how to mock this request, I ask to find better way to do it. Why I need to mock request from .run block if I test, for example, directive? This is my vision. It might be wrong.
@n8m well, this at least makes it so that you don't have to add the request to each individual test, just once per test file
@n8m I don't think you want to set add this request for ALL tests, because the tests that don't need to mock this request will fail if they don't trigger the expected call
I didn't going to add mock request individually to each test. Of course I would use beforeEach block. But I'm trying to find another way. Thanks anyway for your answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.