美文网首页
AngularJs单元测试

AngularJs单元测试

作者: real_ting | 来源:发表于2018-11-12 17:06 被阅读0次

    因为项目要求,需要对一个angularjs项目进行单元测试,所以就去简单学习了一下,主要利用Karma和Jasmine来进行ng模块的单元测试。

    介绍

    Karma

    Karma是一个基于Node.js的JavaScript测试执行过程管理工具(Test Runner)。该工具可用于测试所有主流Web浏览器,也可集成到CI(Continuous integration)工具,也可和其他代码编辑器一起使用。这个测试工具的一个强大特性就是它可以监控文件的变化,然后自动执行,通过console.log显示测试结果。

    Jasmine

    Jasmine是一个用域JS代码测试的行为驱动开发的框架,它不依赖于任何其他的JS框架以及DOM,是一个简洁及友好的API测试库。

    安装

    在Karma的官方文档中,介绍的有安装方法。
    首先你的电脑上需要安装的有Node.js,目前支持的Node.js版本有6.x, 8.x, 10.x。

    # Install Karma:
    $ npm install karma --save-dev
    
    # Install plugins that your project needs:
    $ npm install karma-jasmine karma-chrome-launcher jasmine-core --save-dev
    

    安装成功后,这些模块会保存在你的项目里的package.json文件的devDependencies属性里。

    # Run Karma:
    $ ./node_modules/karma/bin/karma start
    

    因为是局部安装,所以需要进入到安装目录下面执行,当然我们也可以全局安装,这样使用起来可能更方便一些。

    $ npm install -g karma-cli
    

    配置

    在项目根目录下,执行

    $ karma init my.conf.js
    

    当然,配置文件的名字可以随意更改,命令执行的时候会询问一些问题,一般使用默认配置就好。执行完之后会生成一个my.conf.js文件,文件内容如下:

    // Karma configuration
    // Generated on Mon Nov 12 2018 16:11:21 GMT+0800 (中国标准时间)
    
    module.exports = function(config) {
      config.set({
    
        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',
    
    
        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],
    
    
        // list of files / patterns to load in the browser
        files: [
        ],
    
    
        // list of files / patterns to exclude
        exclude: [
        ],
    
    
        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
        },
    
    
        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['progress'],
    
    
        // web server port
        port: 9876,
    
    
        // enable / disable colors in the output (reporters and logs)
        colors: true,
    
    
        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,
    
    
        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,
    
    
        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['Chrome'],
    
    
        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: false,
    
        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: Infinity
      })
    }
    
    # Start Karma using your configuration:
    $ karma start my.conf.js
    

    执行上述命令会自动打开一个浏览器,可以用来Debug。


    Karma

    至此,我们测试环境已经配置好了,下面结合具体项目来进行测试。

    实例

    准备

    因为angularjs是通过依赖注入的方式来加载以及实例化的,所以为了方便配合jasmine来编写测试脚本,官方提供了angular-mock来提供模块定义,加载,注入等。所以还需要安装一下angular-mocks,我的项目目录如下,因为我的Karma是全局安装的,所以没有node_modules文件。


    项目目录

    可以看到我需要测试的文件是index.js,测试用例在spec目录下,对应的是index.spec.js。
    接下来我们结合项目更改一下Karma配置文件,把依赖和待测试文件放到files数组中。

    // list of files / patterns to load in the browser
        files: [
            './bower_components/angular/angular.js',
            './bower_components/angular-mocks/angular-mocks.js',
            './src/js/*.js',
            './src/spec/*[sS]pec.js'
        ]
    

    index.js内容如下,包括controller, services, directive和filter:

    var app = angular.module('myApp', []);
    app.controller('myAppController', ['$scope', 'myService', function($scope, myService) {
        $scope.count = 0;
        $scope.add = function() {
           $scope.count ++;
        };
    
        $scope.reset = function() {
            $scope.count = 0;
        };
        
        $scope.get = function () {
            myService.getData().then(function (res) {
                $scope.data = res.data;
            })
        }
    }]);
    
    app.service('myService', ['$http', function ($http) {
        return {
            getData: getData
        }
    
        function getData() {
            return $http.get("http://rapapi.org/mockjsdata/29387/getCartList");
        }
    }])
    
    app.directive('currentDate', function() {
      return {
        restrict: 'E',
        replace: 'false',
        template: `<h4 style="margin: 100px auto">${new Date().getFullYear()}</h4>`
      }
    });
    
    app.filter('percentage', function() {
        return function(num) {
            if (num == null) {
                return '0%';
            } else {
                return (parseFloat(num) * 100).toFixed(0) + '%';
            }
        };
    });
    

    index.spec.js文件,包括对controller,services,directive和filter的测试,代码中都标有注释,就不详细说了:

    describe('myApp', function() {
        // 引入模块
        beforeEach(module('myApp'));
    
        // 测试controller
        describe('test controller', function () {
            var scope, ctrl;
            beforeEach(inject(function($rootScope, $controller) {
                // scope是rootScope new出来的
                scope = $rootScope.$new();
                ctrl = $controller('myAppController', {$scope: scope});
            }));
            it('addFunction', inject(function() {
                expect(scope.count).toEqual(0);
                scope.add();
                expect(scope.count).toEqual(1);
    
            }));
    
            it('resetFunction', inject(function () {
                scope.reset();
                expect(scope.count).toEqual(0);
            }));
    
            // 测试services
            it('getFunction', inject(function ($injector) {
                // $httpBackend 是由angular mock提供的一个模拟http请求返回服务
                // 可以用它来模拟http请求的返回值
                // 这里通过$injector来获取它的实例
                var $httpBackend = $injector.get('$httpBackend');
                $httpBackend.when('GET', 'http://rapapi.org/mockjsdata/29387/getCartList').respond({
                    age: '18',
                    name: 'tina'
                })
                scope.get();
    
                //把http的异步转为同步,要求$httpBackend立刻返回数据
                $httpBackend.flush();
    
                expect(scope.data).toEqual({
                    age: '18',
                    name: 'tina'
                });
            }))
        })
    
        // 测试过滤器
        describe('test filter', function() {
            it("should return 60", inject(function (percentageFilter) {
                expect(percentageFilter(0.6)).toBe('60%');
            }))
        })
    
        // 测试指令
        describe('test directive', function() {
            it("should get 2018", inject(function ($compile, $rootScope) {
                scope = $rootScope.$new();
                // 调用指令
                elem = angular.element('<current-date></current-date>');
                // 编译
                $compile(elem)(scope);
                console.log(elem.html());
                expect(elem.html()).toEqual('2018')
            }))
        })
    });
    

    至于测试用例怎么书写就不详细介绍了,可参考文档,也可参考博客

    执行

    在package.json文件中添加

    "scripts": {
        "test": "karma start karma.config.js"
      }
    

    终端输入

    npm test
    

    效果如下:


    效果

    相关文章

      网友评论

          本文标题:AngularJs单元测试

          本文链接:https://www.haomeiwen.com/subject/hwjcfqtx.html