Angular resource testing: $httpBackend.flush() cause Unexpected request

10,061

Solution 1

I have finally found solution:

I tried to follow this: other post

So I added $templateCache:

'use strict';

var $httpBackend;

describe('Service: AddressService', function () {

    beforeEach(module('myApp'));

    beforeEach(inject(function ($injector, $templateChache) {
        $templateCache.put('views/home.html', '.<template-goes-here />');
        var url_get = 'api/v1/models/address/5';

        var response_get = {
            address_line_1: '8 Austin House Netly Road',
            address_line_2: 'Ilford IR2 7ND'
        };

        $httpBackend = $injector.get('$httpBackend');

        $httpBackend.whenGET(url_get).respond(response_get);

    }));

    describe('AddressService get test', function () {
        it('Tests get address', inject(function (AddressService) {
            var address = AddressService.get({ id: '5'});
            $httpBackend.flush();
            expect(address.address_line_1).toEqual('8 Austin House Netly Road');
            expect(address.address_line_2).toEqual('Ilford IR2 7ND');
        }));
    });
});

Solution 2

the error is caused by your test attempting to load the main page for your app. Since you have not told the test to expect this server call, an error is returned. See the documentation for $httpBackend for clarification on this point.

Your $templateCache workaround is designed for unit testing directives not anything else. You were quite close with:

$httpBackend.when('GET', /\.html$/).passThrough();

Since you don't need to do anything with the actual template file it's a safe and simple work around to add this to your beforeEach() block.

$httpBackend.whenGET(/\.html$/).respond('');

This stops you getting the TypeError you had.

TypeError: Object #<Object> has no method 'passThrough'

I had the same issue in my unit tests after upgrading to a new version of Angular JS and using respond('') worked fine.

Share:
10,061
Bartosz Dabrowski
Author by

Bartosz Dabrowski

Software development is all about making decisions - eventually. Programmer makes several or even a hundred choices that impact the product in a single day. Making decisions are the most difficult tasks that we encounter but what is possible if we get them right?

Updated on June 13, 2022

Comments

  • Bartosz Dabrowski
    Bartosz Dabrowski almost 2 years

    I want to test angularjs resource.

    'use strict';
    
    /**
     * AddressService provides functionality to use address resource in easy way.
     *
     * This is an example usage of method:
     *
     * `get`:
     *
         var a = AddressService.get({id: '1'},
             function (data) {
                // Work here with your resource
             }
         );
     *
     */
    App.factory('AddressService', function ($resource, $rootScope) {
        var url = [
                $rootScope.GLOBALS.API_PATH,
                $rootScope.GLOBALS.API_VERSION,
                'models/address/:id'
            ].join('/'),
    
            actions = {
                'get': {
                    method: 'GET',
                    params: {id: '@id'}
                }
            };
        return $resource(url, {}, actions);
    });
    

    I created the test:

    'use strict';
    
    var $httpBackend;
    
    describe('Service: AddressService', function () {
    
        beforeEach(module('myApp'));
    
        beforeEach(inject(function ($injector) {
            var url_get = 'api/v1/models/address/5';
    
            var response_get = {
                address_line_1: '8 Austin House Netly Road',
                address_line_2: 'Ilford IR2 7ND'
            };
    
            $httpBackend = $injector.get('$httpBackend');
    
            $httpBackend.whenGET(url_get).respond(response_get);
    
        }));
    
        describe('AddressService get test', function () {
            it('Tests get address', inject(function (AddressService) {
                var address = AddressService.get({ id: '5'});
                $httpBackend.flush();
                expect(address.address_line_1).toEqual('8 Austin House Netly Road');
                expect(address.address_line_2).toEqual('Ilford IR2 7ND');
            }));
        });
    });
    

    I am not experienced with angular very well. I have set jasmine in karma.config.js. AngularJS v1.0.6 Yoeman and Grunt manage project.

    I try grunt test

    Running "karma:unit" (karma) task
    INFO [karma]: Karma server started at http://localhost:8080/
    INFO [launcher]: Starting browser Chrome
    INFO [Chrome 27.0 (Linux)]: Connected on socket id RFFUY5bW8Hb5eTu0n-8L
    Chrome 27.0 (Linux) Service: AddressService AddressService get Tests get address FAILED
            Error: Unexpected request: GET views/home.html
            No more request expected
                at Error (<anonymous>)
                at $httpBackend (/home/bart/y/projects/x/frontend/app/components/angular-mocks/angular-mocks.js:910:9)
                at sendReq (/home/bart/y/projects/x/frontend/app/components/angular/angular.js:9087:9)
                at $http (/home/bart/y/projects/x/frontend/app/components/angular/angular.js:8878:17)
                at Function.$http.(anonymous function) [as get] (/home/bart/y/projects/x/frontend/app/components/angular/angular.js:9021:18)
                at $q.when.then.then.next.locals (/home/bart/y/projects/x/frontend/app/components/angular/angular.js:7394:34)
                at wrappedCallback (/home/bart/y/projects/x/frontend/app/components/angular/angular.js:6797:59)
                at wrappedCallback (/home/bart/y/projects/x/frontend/app/components/angular/angular.js:6797:59)
                at /home/bart/y/projects/x/frontend/app/components/angular/angular.js:6834:26
                at Object.Scope.$eval (/home/bart/y/projects/x/frontend/app/components/angular/angular.js:8011:28)
            Error: Declaration Location
                at window.jasmine.window.inject.angular.mock.inject (/home/bart/y/projects/x/frontend/app/components/angular-mocks/angular-mocks.js:1744:25)
                at null.<anonymous> (/home/bart/y/projects/x/frontend/test/spec/services/userdata/AddressService.js:32:30)
                at null.<anonymous> (/home/bart/y/projects/x/frontend/test/spec/services/userdata/AddressService.js:31:5)
                at /home/bart/y/projects/x/frontend/test/spec/services/userdata/AddressService.js:5:1
    ..................................................................
    Chrome 27.0 (Linux): Executed 67 of 67 (1 FAILED) (0.343 secs / 0.179 secs)
    Warning: Task "karma:unit" failed. Use --force to continue.
    

    If I remove $httpBackend.flush() in test. Test is passing. But I am getting undefined from address. I saw examples: example all use the flush() But only I get silly exception: Error: Unexpected request: GET views/home.html

    views/home.html is my view in project directory. I have no idea how solve my problem I could not find any solution. Am I missing the point somehow?

    Can anybody see mistake in my code? All suggestions will be appreciate.

    EDIT

    I have found that I need to use this:

    $httpBackend.when('GET', /\.html$/).passThrough();
    

    But another problem is I am getting:

    TypeError: Object #<Object> has no method 'passThrough'
    
  • Paolo del Mundo
    Paolo del Mundo over 10 years
    Why is the templateCache important? It seems it has nothing to do with an API service.
  • Pwnna
    Pwnna over 10 years
    I agree. This seems like an awful hack to ignore the problem. I'm encountering the same issues now and I'm not sure why this is the case...
  • Bartosz Dabrowski
    Bartosz Dabrowski about 10 years
    These are unit tests and you have to extract specific units (service in this case) to test. Remove all other dependencies even templates which are simply mocked here. I don't know better way to do it have no idea about core angular flow either. And this question isn't closed yet.
  • Stephane
    Stephane about 9 years
    Isn't it possible instead to avoid the $http service making such a request to the application main page ?
  • akostadinov
    akostadinov over 3 years
    This is a nice simple resolution to fix individual test cases and I will probably stick to it. For more ideas check github.com/meanjs/mean/issues/198