使用 Node.js、Gulp.js 和 Mocha 对 angularjs 控制器进行单元测试



我正在尝试使用Node.js对angularjs控制器进行单元测试。我正在使用gulp.js和摩卡通过gulp-mocha来运行测试。

这是我的gulpfile.js现在的样子:

(function () {
    var gulp = require('gulp');
    var mocha = require('gulp-mocha');
    gulp.task('default', function () {
        return gulp
            .src('Scripts/Tests/*.js', { read: false })
            .pipe(mocha({ 
                ui: 'tdd', 
                reporter: 'dot',
                globals: {
                    angular: require('./Scripts/angular.js')
                }
            }));
    });
})();

这是正在测试的代码:

(function () {
    var application = angular.module('Main');
    application.controller('MainController', ['$scope', function ($scope) {
        $scope.isDisabled = function () {
            return true;
        };
    }]);
})();

这是测试文件本身:

(function () {
    var chai = require('chai');
    var assert = chai.assert;
    angular.module('Main', []);  // Create an empty module  
    require('../MainController.js');  // Fill the module with the controller
    suite('Main Controller', function () {
        test('isDisabled always true', function () {
            var controllerFactory = angular.injector.get('$controller');
            var controller  = controllerFactory('MainController', {
                '$scope': {}
            });
            var result = controller.isDisabled();
            assert.isTrue(result);
        });
    });
})();

我需要将角度设置为全局,以便我的测试和我正在测试的文件正常工作。但是,在gulpfile.js中调用require给了我一个Reference Error: window is not defined错误。这是有道理的,因为我在 Node.js 中运行。

我需要做什么才能在 Node.js 中加载角度?

正如

@unobf所说(以及angularjs文档所说(,从Node测试角度的诀窍.js是使用Karma。这意味着通过npm install安装karmakarma-mocha,以及karma-chrome-launcherkarma-ie-launcherkarma-firefox-launcher(或其他任何东西(。

然后我基本上不得不从头开始重做我的gulp.js文件:

(function () {
    var gulp = require('gulp');
    var karma = require('karma').server;
    gulp.task('runTests', function (done) {
        karma.start({
            configFile: __dirname + '/karma.config.js',
            singleRun: true
        }, done);
    });
    gulp.task('default', ['runTests']);
})();

我还必须创建一个karma.config.js文件来配置业力以使用Chrome,Firefox,IE和摩卡。在同一个文件中,我将 mocha 配置为使用 tdd UI 和点报告器:

module.exports = function(config) {
    config.set({
        browsers: ['Chrome', 'Firefox', 'IE'],
        frameworks: ['mocha'],
        files: [
            './Scripts/angular.js',
            './Scripts/chai.js',
            './Scripts/*.js',
            './Scripts/Tests/*.js'
        ],
        singleRun: true,
        client: {
            mocha: {
                reporter: 'dot',
                ui: 'tdd'
            }
        }
    });
};

我了解到您必须首先指定angularjs,chai.js等,以便首先拾取它们并在全局范围内用于其他文件。同样,要测试的代码的文件必须在测试文件之前列出。

正在测试的代码根本没有改变。一旦我的测试开始运行,我意识到我的测试被破坏了,最终看起来像这样通过:

(function () {
    var assert = chai.assert;
    suite('Main Controller', function () {
        test('isDisabled always true', function () {
            var injector = angular.injector(['ng', 'Main']);
            var $controller = injector.get('$controller');
            var scope = {};
            var controller  = $controller('MainController', {
                '$scope': scope
            });
            var result = scope.isDisabled();
            assert.isTrue(result);
        });
    });
})();

最大的收获是控制器只是填充$scope对象。我改为在$scope对象上调用isDisabled()。当然,获取控制器是一项繁重的工作,因此使用 angular-mocks.js 提供的inject方法更有意义:

(function () {
    var assert = chai.assert;
    suite('Main Controller', function () {
        var $scope = {};
        setup(function () {
            module('Main');
            inject(function ($controller) {
                $controller('MainController', {
                    '$scope': $scope
                });
            });
        });
        test('isDisabled always true', inject(function ($controller) {          
            var result = $scope.isDisabled();
            assert.isTrue(result);
        }));
    });
})();

希望这足以让任何尝试使用 Node.js 和 mocha 来测试 angularjs 代码的人入门。

我在Grunt中这样做,但同样的原则也适用于Gulp。您需要注入"角度模拟.js"文件才能模拟依赖注入。我正在使用 Karma http://karma-runner.github.io/0.12/index.html 来执行此操作,并在我的 karma.conf.js 文件中设置它,如下所示:

module.exports = function(config){
  config.set({
    basePath : '../../',
    files : [
      'bower_components/angular/angular.js',
      'bower_components/angular-mocks/angular-mocks.js',
      ...

然后,您可以将$controller注入到测试中,并执行诸如测试控制器初始化之类的操作。下面的测试是初始化范围,然后测试控制器是否正在向范围添加方法(注意,我使用的是 Jasmine,但摩卡也可以这样做(,但 Jasmine 带有一些不错的内置间谍功能。

describe('analysisController', function () {
    var scope, state;
    beforeEach(function () {
        module('analysis');
        scope = {
            $apply:jasmine.createSpy(),
            ws: {
                registerCallback:jasmine.createSpy(),
                sendMessage:jasmine.createSpy()
            }
        },
        state = {
            go : jasmine.createSpy()
        };
    });
    it('should add a bunch of methods to the scope', inject(function ($controller) {
        $controller('analysisController', {
            $scope : scope,
            $state: state
        });
        expect(typeof scope.colorContrast).toBe('function');
        expect(typeof scope.XPathFromIssue).toBe('function');
    }));
    ...

最新更新