Angular,基本测试无效

Angular, basic test not working

控制器:

angular.module('ngApp', [
    'templates-app',
    'templates-common',
    'ngApp.home',
    'ui.router'
])

.config(function myAppConfig($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('/home');
})

.run(function run() {})

.controller('AppCtrl', function AppCtrl($scope) {
    $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
        if (angular.isDefined(toState.data.pageTitle)) {
            $scope.pageTitle = toState.data.pageTitle + ' | App';
        }
    });
});

测试:

describe('AppCtrl', function() {

    beforeEach(module('ngApp'));

    var $controller;

    beforeEach(inject(function(_$controller_) {
        $controller = _$controller_;
    }));

    describe('$scope.pageTitle', function() {
        it('should set pageTitle', inject(function() {
            var $scope = {};
            var AppCtrl = $controller('AppCtrl', { $scope: $scope });
            expect(true).toBe(true);
        }));
    });
});

我现在没有测试任何东西,只是加载控制器。然而这失败了

Chrome 41.0.2272 (Mac OS X 10.10.2) AppCtrl $scope.pageTitle should set pageTitle FAILED
    TypeError: undefined is not a function
        at new AppCtrl (/src/app/app.js:15:9)
        at invoke (/vendor/angular/angular.js:4203:17)
        at Object.instantiate (/vendor/angular/angular.js:4211:27)
        at /vendor/angular/angular.js:8501:28
        at /vendor/angular-mocks/angular-mocks.js:1878:12
        at Object.<anonymous> (/src/app/app.spec.js:14:19)
        at Object.invoke (/vendor/angular/angular.js:4203:17)
        at Object.workFn (/vendor/angular-mocks/angular-mocks.js:2436:20)
    Error: Declaration Location
        at window.inject.angular.mock.inject (/vendor/angular-mocks/angular-mocks.js:2407:25)
        at Suite.<anonymous> (/src/app/app.spec.js:12:30)
        at Suite.<anonymous> (/src/app/app.spec.js:11:2)
        at /src/app/app.spec.js:1:1

我的测试设置有什么问题吗?

实测:

describe('$scope.pageTitle', function() {
    it('should be defiend after stateChange', inject(function() {
        var $scope = {};
        var AppCtrl = createController('AppCtrl');
        scope.$broadcast('$stateChangeSuccess', {
            data: {
                pageTitle: 'bar'
            }
        });
        expect(scope.pageTitle).toBeDefined();
    }));
});

我认为问题在于您注入控制器的范围和 $scope.$on... 。试试这个:

describe('AppCtrl', function() {

beforeEach(module('ngApp'));

var $controller, $scope;

beforeEach(inject(function(_$controller_, _$rootScope_) {
    $controller = _$controller_;
    $rootScope = _$rootScope_.$new();
}));

describe('$scope.pageTitle', function() {
    it('should set pageTitle', inject(function() {            
        var AppCtrl = $controller('AppCtrl', { $scope: $scope });
        expect(true).toBe(true);
    }));
});
});

您需要从 $rootScope 创建范围并注入它:

    beforeEach(inject(function (_$controller_, $rootScope) {
        $controller = _$controller_;
        scope = $rootScope.$new();
        createController = function (ctrlName) {
          return $controller(ctrlName, {
            '$scope': scope
         });
       };
    }));

通过这种方式,您可以使用 createController 功能,并使用:

var AppCtrl = createController('AppCtrl');

因为有控制器。

这是一个有效的 jsfiddle: http://jsfiddle.net/Lbs6sk0k/2/

编辑$scope 哪里是空的? 如果我在这里放一个 console.log

.controller('AppCtrl', function AppCtrl($scope) {
    console.log($scope);

我可以看到这个:

编辑 2:

将范围设置为全局变量:

describe('AppCtrl', function () {

    beforeEach(module('ngApp'));
    var $controller;
    var scope;

然后,在你的测试用例中,你可以使用它:

it('should set pageTitle', inject(function () {
    var $scope = scope;

用你的新测试用例更新了 jsfiddle:http://jsfiddle.net/Lbs6sk0k/3/