【问题标题】:Provider $get method is not called in jasmine unit test茉莉花单元测试中未调用提供程序 $get 方法
【发布时间】:2017-02-12 16:38:33
【问题描述】:

我在 app.js 中使用自定义提供程序进行后端调用,然后在控制器中注入该提供程序并获得承诺结果(我这样做是因为在每个控制器中调用 getLoggedUser 我只是从提供程序获取结果)和例如,我不会拨打 10 次电话,而是在提供者中拨打一次)。但是我无法测试此提供程序 $get 方法并且测试失败,因为从未进行过后端调用。

我收到错误:

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();
                }];
        });

测试

/* 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();
            });
        });
    });
})();

控制器

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

如果我在提供者中做这样的事情:

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

然后我可以在测试中做这样的事情:

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

这将通过工作测试,但是当我使用 userProvider.loggedUser() 时,在每个控件中使用这种方法。然后它将进行额外的后端调用,并且只使用一次后端调用。

Ceylan 更新

如果我确实喜欢你建议调用服务,并在方法调用 getLoggedUser 从另一个服务中进行额外的调用...而不是像我一样没有功能。

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

服务

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

【问题讨论】:

  • 在$httpBackend中定义期望的url请求
  • @CeylanMumunKocabaş 我添加了函数:it("应该调用 getLogged 函数", function() { ListingController.getLoggedUser(); $httpBackend.expectGET('localhost:8443/user/current').respond(200); $httpBackend.flush( ); }); 但同样的错误......
  • $httpBackend.when('GET', 'localhost:8443/user/current').respond(200); $httpBackend.expect('GET', 'localhost:8443/user/current');
  • 并确保网址相同或使用正则表达式

标签: javascript angularjs unit-testing karma-jasmine provider


【解决方案1】:

这是基本结构:

$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();

请务必定义您的 httpBackend 变量 - var httpBackend = $httpBackend;

而且为了检查服务是否被调用,你必须使用 spy。

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

//here goes the function that calls the service

expect(service.method).toHaveBeenCalled();

你结合上面的两个块,你应该可以实现你想要的。

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();
            });
        });

关于您的服务:

function myService(){
    var svc = this;

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

【讨论】:

  • 是的,我知道我需要使用 spy.. 但问题是这个提供程序没有功能......我没有方法,那么在 spyOn 中添加哪个方法?这是我的担心..
  • 将你的功能放入 service.method 并返回服务。
  • 我不确定我是否遵循.. 获取登录用户的功能在返回 promse 的其他服务中。
  • 我尝试了使用新服务和调用方法的方法,但正如我所说,每次我在控制器中调用 userProvider.myMethod().then 时都会进行后端调用...
猜你喜欢
  • 1970-01-01
  • 2016-07-13
  • 1970-01-01
  • 2017-09-27
  • 1970-01-01
  • 2022-01-23
  • 2020-11-25
  • 2018-07-17
相关资源
最近更新 更多