AngularJs单元测试

2018-11-12  本文已影响0人  real_ting

因为项目要求,需要对一个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

效果如下:


效果
上一篇下一篇

猜你喜欢

热点阅读