AngularJS Karma 单元测试

AngularJS Karma Unit Testing

只是在摆弄 moviedb api 并尝试为我的 navigateGenre 函数编写测试,但我不断收到错误消息:

TypeError: Cannot read property 'id' of undefined

这是规格和控制器代码:

规格:

describe('Genre List Controller', function(){
    var ctrl, scope;

    beforeEach(module('MovieFinder'));

    beforeEach(inject(function($controller, $route, $rootScope, _$location_, _GenreListFactory_){
        scope = $rootScope.$new();
        var $location = _$location_;
        var GenreListFactory = _GenreListFactory_;

        $route.current = {
            params: {
                genreId: 18
            }
        };

        ctrl = $controller('GenreListCtrl', {
            $scope: scope,
            $location: $location,
            GenreListFactory: GenreListFactory,
            $route: $route
        });
    }));

    fit('should route to correct genre when navigateGenre() is called',
    inject(function($httpBackend, $rootScope, $route, $location){
        $httpBackend.expect('JSONP', 'http://api.themoviedb.org/3/genre/movie/list?api_key=&callback=JSON_CALLBACK').respond(200);
        $httpBackend.expect('GET', 'js/genre-detail/genre-detail.html').respond(200);

        $rootScope.$apply(function(){
            $location.path('/genre/18');
        });

        $rootScope.$apply(function(){
            scope.navigateGenre();
        });

        expect($route.current.originalPath).toBe('/genre/:genreId');
        expect($route.current.params.genreId).toBe();

    }));
});

控制器:

MovieFinder
    .controller('GenreListCtrl', ['$scope', '$route', '$location', 'GenreListFactory', function($scope, $route, $location, GenreListFactory){
        GenreListFactory().then(function(genres){
            console.log('GenreListCtrl', genres);
            $scope.test = 'test';
            $scope.genreList = [{id: null, name: 'Select a Genre'}];
            genres.data.genres.forEach(function(genre){
                //console.log(genre.name);
                $scope.genreList.push(genre);
            });
            $scope.selectedGenre = $scope.genreList[0];
        });
        $scope.navigateGenre = function(){
            if($scope.selectedGenre.id !== null){
                $location.path('genre/' + $scope.selectedGenre.id);
                $scope.selectedGenre = $scope.genreList[0];
            }
        };
    }]);

如有任何帮助,我们将不胜感激。 如果我需要添加任何内容,请告诉我。

终于能够让这个东西工作了。 我所做的是将 $scope.genreList and $scope.selectedGenre 移出 .then()。 $httpBackend.expect 设置为以 200 响应,但如果我们不模拟延迟承诺并解决它,.then 将永远不会触发。

重构代码如下:

控制器:

MovieFinder
    .controller('GenreListCtrl', ['$scope', '$route', '$location', 'GenreListFactory', function($scope, $route, $location, GenreListFactory){
        $scope.genreList = [{id: null, name: 'Select a Genre'}];
        $scope.selectedGenre = $scope.genreList[0];

        GenreListFactory().then(function(genres){
            console.log('GenreListCtrl', genres);
            $scope.test = 'test';
            genres.data.genres.forEach(function(genre){
                //console.log(genre.name);
                $scope.genreList.push(genre);
            });
            console.log('genreList', $scope.genreList);
        });
        console.log('genreList', $scope.genreList);
        $scope.navigateGenre = function(){
            if($scope.selectedGenre.id !== null){
                $location.path('genre/' + $scope.selectedGenre.id);
                $scope.selectedGenre = $scope.genreList[0];
            }
        };
    }]);  

规格:

describe('Genre List Controller', function(){
        var ctrl, scope;

        beforeEach(module('MovieFinder'));

        beforeEach(inject(function($controller, $route, $rootScope, _$location_, _GenreListFactory_){
            scope = $rootScope.$new();
            var $location = _$location_;
            var GenreListFactory = _GenreListFactory_;

            $route.current = {
                params: {
                    genreId: 18
                }
            };

            scope.selectedGenre = {
                id: 80,
                name: 'Crime'
            };

            ctrl = $controller('GenreListCtrl', {
                $scope: scope,
                $location: $location,
                GenreListFactory: GenreListFactory,
                $route: $route
            });
        }));

        it('should route to correct genre when navigateGenre() is called',
        inject(function($httpBackend, $rootScope, $route, $location){
            $httpBackend.expect('JSONP', 'http://api.themoviedb.org/3/genre/movie/list?api_key=990ba45b90f56c57b4e00a54fc773d8c&callback=JSON_CALLBACK').respond(200);
            $httpBackend.expect('GET', 'js/genre-detail/genre-detail.html').respond(200);

            $rootScope.$apply(function(){
                $location.path('/genre/18');
            });

            $rootScope.$apply(function(){
                /*scope.selectedGenre.id = 80;*/
                scope.navigateGenre();
            });

            expect($route.current.params.genreId).toBe('18');
            expect(scope.selectedGenre.id).toBe(null);

        }));
    });