简体   繁体   中英

Provider $get method is not called in jasmine unit test

I am using custom provider in my app.js to make backend call and then in controllers just injecting that provider and getting promise result (I make this because instead to call getLoggedUser in every controller I am just getting results from provider) and instead of making 10 calls for example I will make just one in provider). But I am unable to test this provider $get method and test is failing because backend call is never made.

I am getting error :

Error: Unexpected request: GET https://localhost:8443/user/current

app.js

 angular.module('app', [
            ...
        ])
        .config(config)
        .run(run)
        .controller('MainCtrl', MainCtrl)
        .value('version', '1.1.0')
        .provider('userProvider', function(){

            this.$get = ['AuthenticationService',
                function(AuthenticationService) {
                    return AuthenticationService.getLoggedUser();
                }];
        });

TEST

/* jshint undef:false*/
(function() {
    'use strict';

    describe('ListingController', function() {
        var listingController, rootScope, scope, q, mockAuthenticationService, $httpBackend, service;
        var provider = {};
        var mockCurrentUser = {
            id: 1782,
            name: "One, Coordinator",
            roleId: [
                3, 10
            ],
            eauthId: "coodinator1"
        };

        beforeEach(module('app'));
        beforeEach(module('listing'));
        beforeEach(function () {
            module(function (userProviderProvider) {
                provider = userProviderProvider;
            });
        });
        beforeEach(inject(function($rootScope, $controller, $q, _$httpBackend_, _AuthenticationService_, userProvider, $injector) {
            rootScope = $rootScope;
            scope = rootScope.$new();
            $httpBackend = _$httpBackend_;
            q = $q;
            mockAuthenticationService = _AuthenticationService_;
           // provider = userProvider;
            service = $injector.invoke(provider.$get);

            rootScope.$digest();

            listingController = $controller('ListingController', {
                $scope : scope,
                mockAuthenticationService : _AuthenticationService_
            });
        }));
        describe('getLogged user and init',function(){
            it("should call getLogged function", function() {
                listingController.getLoggedUser();

                rootScope.$digest();

                expect(service).toHaveBeenCalled();
            });
        });
    });
})();

Controller

function getLoggedUser() {
            userProvider.then(function (data){
               // Here I am getting result from back end call from provider     which is good
        });

If I make something like this in provider:

this.$get = function (AuthenticationService) {
                return {
                    loggedUser : function() {
                        return AuthenticationService.getLoggedUser();
                    }
                }
            }

I can then make something like this in test:

 spyOn(provider , 'loggedUser').and.callFake(function() {
                var deferred = q.defer();
                deferred.resolve(mockCurrentUser);
                return deferred.promise;
            });

and this will work test will pass, but with this approach in every controlle when I user userProvider.loggedUser().then it will make additional back end call and with above one only once back end call will be made.

Update for Ceylan

If I do like you suggest to call service and in method call getLoggedUser from another service additional calls are being made every time...not just one like I have without function.

.provider('userProvider', function(){
            return {
                $get: function(AuthenticationService) {
                    return new userService(AuthenticationService);
                }
            }
        });

service

   function userService(AuthenticationService) {
        this.getLoggedUser  = function() {
           return  AuthenticationService.getLoggedUser();
        }
    }

Here is the basic structure:

$httpBackend.when('GET', 'localhost:8443/user/current').respond(200, /*optional response callback function*/); 
$httpBackend.expect('GET', 'localhost:8443/user/current');

//here goes the function that makes the actual http request

$httpBackend.flush();

Be sure that you define your httpBackend var - var httpBackend = $httpBackend; .

And also in order to check did the service was called, you must use spy.

spyOn(service, 'method').and.callThrough();

//here goes the function that calls the service

expect(service.method).toHaveBeenCalled();

You combine the two blocks above and you should be able to achieve what you want.

describe('something',function(){
            it("should do something", function() {

                spyOn(service, 'method').and.callThrough();

                $httpBackend.when('GET', 'localhost:8443/user/current').respond(200,/*optional response callback function*/); 
                $httpBackend.expect('GET', 'localhost:8443/user/current');

                //call the function that makes http request and calls your service

                rootScope.$digest();
                $httpBackend.flush();

                expect(service.method).toHaveBeenCalled();
            });
        });

And about your service:

function myService(){
    var svc = this;

    svc.myMethod = function(){
         return someDataOrPromise;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM