我正在尝试测试我的一个控制器。我的问题是创建的$LoginController对象始终是一个空对象,而我的方法都在范围对象上。然后当我想测试
hasError函数,我收到一条消息:

TypeError:“未定义”不是对象(评估“ $ route.current.params”)

这是我的测试:

describe('login', function () {
        var $LoginController = null, $scope, $route, $location, $httpBackend;
        beforeEach(module('common.base64'));
        beforeEach(module('myapp.user'));

        beforeEach(inject(function ($injector, $controller, $rootScope,
                                    _$location_, _$timeout_, _$route_, _Base64_)
        {
            $httpBackend = $injector.get('$httpBackend');
            $scope = $rootScope.$new();
            $route = _$route_;
            $location = _$location_;
            $LoginController = $controller('LoginController', {
                $scope : $scope, $http: $httpBackend, $location: _$location_,
                $timeout: _$timeout_, $route: _$route_, Base64: _Base64_}
            );
            console.log($LoginController); // <-- Log: {}
            console.log($scope);           // <-- Log: { <lots of stuff> }
        }));

        describe('LoginController', function() {
            it('should have been injected', inject(function () {
                    expect($LoginController).toBeTruthy();
                }
            ));
        });

        describe('hasError', function () {
                it('should return error', inject(function () {
                        $location.url('/login?loginError=true');

                        expect($scope.hasError).toBeTruthy();
                                   // ^-- hasError is defined!
                        expect($LoginController.hasError).toBeTruthy();
                        //                      ^-- hasError is undefined!
                    }
                ));
            }
        );
    }
);


在我的LoginController中,hasError函数的定义如下:

    $scope.hasError = function () {
        if($route.current.params) {
            if ($route.current.params['loginError']) {
                return "error";
            } else {
                return "";
            }
        }
        return "";
    };


然后将其注入到elements类属性中。那么我的哪段代码是错误的,是控制器还是测试?

最佳答案

你的测试是。

由于您在此处的测试中未使用任何路由,因此将没有当前的路由可从中提取。

您可以根据需要明确设置此设置

_$route_.current = {
  params: {
    loginError: 12345
  }
};


如果您使用的是$location模块,那么ng-mock和其他一些东西都将被模拟物替换掉。

因此,更改$location不会触发路由更改。

更好的解决方案是将控制器更改为使用$routeParams依赖关系,而不是访问当前路由本身。这样,您就可以在测试创建过程中将其传递出去。

if($routeParams && $routeParams.loginError) {
   return "error";
}

return "";


然后在测试中,您只需输入$routeParams

$LoginController = $controller('LoginController', {
  $scope : $scope, $http: $httpBackend, $location: _$location_,
  $timeout: _$timeout_,

  // Mock out $routeParams here:
  $routeParams: {loginError: 'blah' },

  Base64: _Base64_}
);

07-24 16:09