Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Node.js、Gulp.js和Mocha对angularjs控制器进行单元测试_Angularjs_Node.js_Unit Testing_Mocha.js_Gulp - Fatal编程技术网

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

使用Node.js、Gulp.js和Mocha对angularjs控制器进行单元测试,angularjs,node.js,unit-testing,mocha.js,gulp,Angularjs,Node.js,Unit Testing,Mocha.js,Gulp,我正在尝试使用Node.js对angularjs控制器进行单元测试。我正在使用gulp.js和mocha通过gulp mocha运行测试 这就是我的gulpfile.js现在的样子: (function () { var gulp = require('gulp'); var mocha = require('gulp-mocha'); gulp.task('default', function () { return gulp

我正在尝试使用Node.js对angularjs控制器进行单元测试。我正在使用gulp.js和mocha通过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
会给我一个
参考错误:窗口未定义
错误。这是有道理的,因为我是在Node.js中运行的


在Node.js中加载angular需要做什么?

我在Grunt中这样做,但同样的原则也适用于Gulp。您需要注入“angularmocks.js”文件,以便能够模拟依赖项注入。我正在使用Karma进行此操作,并在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,但mocha也可以这样做),但是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');
    }));
    ...
正如@unobf所说(以及angularjs文档所说),从Node.js测试angular的诀窍是使用Karma。这意味着安装
karma
karma mocha
,以及
karma chrome launcher
karma ie launcher
karma firefox launcher
(或其他)通过
npm安装

然后我基本上必须从头开始重做我的
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
文件,将karma配置为使用Chrome、Firefox和mocha。在同一个文件中,我将mocha配置为使用tdd UI和dot reporter:

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()
。当然,获取控制器需要大量工作,因此使用
angularmocks.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代码的人开始学习。

你能告诉我全局
inject
是从哪里来的吗?有没有其他方法来获取
$controller
?我最终只是通过
angular.injector(['ng','Main']).get('$controller')
创建了一个注入器。尽管如此,我还是会在我的真实项目中使用angular mock。谢谢你的详细解释。