2014-12-21 134 views
2

我想单元测试一个使用Node.js的angularjs控制器。我正在使用gulp.js和mocha通过gulp-mocha运行测试。单元测试使用Node.js,Gulp.js和摩卡的angularjs控制器

这是我的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); 
     }); 

    }); 

})(); 

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

在Node.js中加载角度需要做些什么?

回答

2

我在Grunt中这样做,但同样的原则适用于Gulp。您需要注入“angular-mocks.js”文件才能模拟依赖注入。我使用噶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', 
     ... 

然后你可以注入一个$控制器到您的测试和做的事情一样测试你的控制器初始化。下面的测试是初始化范围,然后测试控制器是否将方法添加到范围中(请注意,我正在使用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'); 
    })); 
    ... 
+1

这里是一个噶玛模块https://github.com/karma-runner/gulp-karma – unobf

+0

你能告诉我全局'inject'来自哪里吗?是否有另一种方法来获取'$ controller'? –

+1

它是由angular-mock声明的,但是Karma也有一些神奇的功能 – unobf

3

正如@unobf所述(以及angularjs文档说),诀窍来测试从Node.js的角是使用噶。这意味着安装karmakarma-mocha,以及karma-chrome-launcher,karma-ie-launcher,karma-firefox-launcher(或其他)通过npm install

然后我基本上从头开始重做我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,火狐,IE与摩卡。在同一文件中,我配置了摩卡使用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的和摩卡来测试angularjs代码。

+0

感谢您的详细解释。 – Alkaline