【问题标题】:Angular Unit Test Jasmine Spy errorAngular 单元测试 Jasmine Spy 错误
【发布时间】:2014-09-13 12:19:22
【问题描述】:

以下控制器收到 TypeError:“未定义”不是函数(正在评估 sessionService.getCurrentPlace())。我有一个模拟服务,该方法被监视。模拟服务上的另一种方法工作正常。我在间谍上尝试过.AndReturns({..}) 以及.AndCallThrough(),但没有运气。知道我错过了什么,还是我要解决这个问题?非常感谢!

控制器:

    'use strict';

angular.module('wallyApp')
    .controller('addGatewayCtrl', function ($scope, $location, $filter, sessionService) {
        /*
            private members
        */
        //set scope from session data
        $scope.processSession = function (places) {
            $scope.currentPlaceId = sessionService.getCurrentPlace();
            if (!$scope.currentPlaceId) {
                $scope.currentPlaceId = places[0].id;
            }
            $scope.place = $filter("getById")(places, $scope.currentPlaceId);
            $scope.ready = true;
        };

        /* 
            setup our scope
        */
        $scope.currentPlaceId = null;
        $scope.place = {};
        $scope.videoSrc = "/videos/gateway-poster.gif";
        $scope.loaded = true;

        /*
            setup controller behaivors
        */

        //set video or gif to show or hide video
        $scope.setVideo = function () {
            $scope.videoSrc = "/videos/gateway.gif";
        };
        $scope.setPoster = function () {
            $scope.videoSrc = "/videos/gateway-poster.gif";
        };
        //initialize scope
        $scope.setVideo();

        //submit form
        $scope.continue = function () {
            $location.path("/setup/pair-gateway");
            return false;
        };
        //cancel
        $scope.back = function () {
            $location.path("/setup/plan-locations");
            return false;
        };
        //wifi
        $scope.gotoWifi = function () {
            $location.path("/setup/wifi");
            return false;
        };


        /*
            setup our services, etc
        */
        //get our places from the cache
        sessionService.get("places").then(function (places) {
            if (!places || places.length < 1) {
                sessionService.refreshPlaces(); //Note we don't care about the promise as our broadcast watch will pick up when ready
            } else {
                $scope.processSession(places);
            }
        }).catch(function (error) {
            //TODO:SSW Call Alert Service??
        });

        //Watch broadcast for changes
        $scope.$on("draco.placesRefreshed", function (event, data) {
            sessionService.get("places").then(function (places) {
                $scope.processSession(places);
            });
        });
    });

单元测试:

    'use strict';

describe('addGatewayCtrl', function () {
    var $q,
        $rootScope,
        $location,
        $scope,
        $filter,
        mockSessionService,

        completePath = "/setup/pair-gateway",
        backPath = "/setup/plan-locations",
        wifiPath = "/setup/wifi",
        sessionDeferred,
        sessionInitDeferred,

        mockPlaces = [{ id: "0001" }];

    beforeEach(module('wallyApp'));

    beforeEach(inject(function (_$q_, _$rootScope_, _$location_, _$filter_) {
        $q = _$q_;
        $location = _$location_;
        $rootScope = _$rootScope_;
        $filter = _$filter_;
    }));

    beforeEach(inject(function ($controller) {
        $scope = $rootScope.$new();

        mockSessionService = {
            get: function (contact) {
                sessionDeferred = $q.defer();
                return sessionDeferred.promise;
            },
            getCurrentPlace: function () {
                return mockPlaces[0].id;
            },
            refreshPlaces: function () {
                sessionInitDeferred = $q.defer();
                return sessionInitDeferred.promise;
            }
        };

        spyOn(mockSessionService, 'get').andCallThrough();
        spyOn(mockSessionService, 'getCurrentPlace').andReturn(mockPlaces[0].id);
        spyOn(mockSessionService, 'refreshPlaces').andCallThrough();

        $controller('addGatewayCtrl', {
            '$scope': $scope,
            '$location': $location,
            '$filter':$filter,
            'sessionService': mockSessionService
        });

    }));

    describe('call session service to get place data ', function () {

        //resolve our mock place and session services
        beforeEach(function () {
            //resolve mocks
            sessionDeferred.resolve(mockPlaces);

            $rootScope.$apply();
        });

        //run tests
        it('should have called sessionService get places', function () {
            expect(mockSessionService.get).toHaveBeenCalledWith("places");
        });
        it('should have called sessionService get currentPlaceId', function () {
            expect(mockSessionService.getCurrentPlace).toHaveBeenCalled();
        });
        it('should have set scope', function () {
            expect($scope.place).toEqual(mockPlaces[0]);
        });

    });

});

【问题讨论】:

    标签: angularjs unit-testing jasmine


    【解决方案1】:

    所以我想通了。使用嵌套延迟,您必须在两者之间调用 $scope.$apply()。以下修复了它(以及对模拟数据响应的一些小的更改,但这些都是微不足道的):

            //resolve promises
            activityMessagesDeferred.resolve(mockActivityMessages);
            $rootScope.$apply();
            $rootScope.$broadcast("draco.sessionRefreshed");
            activityCountDeferred.resolve(mockActivityCount);
            $rootScope.$apply();
    
            placesDeferred.resolve(mockPlaces);
            activityListDeferred.resolve(mockActivities);
            $rootScope.$apply();
    

    【讨论】:

    • 使用$rootScope.$digest(); 就足够了,这样可以加快测试速度。
    猜你喜欢
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    • 2020-04-02
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 2017-11-18
    • 1970-01-01
    相关资源
    最近更新 更多