2014年10月27日 星期一

AngularJS 教學 - Controller 測試

這篇要簡單介紹一下 AngularJS Controller 的測試該如何實現

以下還是用 Karma + Jasmine 來進行測試,如果不熟悉這些可以先看之前寫的文章 AngularJS 教學 - 單元測試(Unit Testing)

首先先列出我們要測試的範例程式,範例很簡單

頁面上有兩個 Button 負責針對 counter 的值進行遞增或遞減

以下是 index.html 的範例程式

<html xmlns="http://www.w3.org/1999/xhtml" ng-app="sampleApp">
     <head>
         <title>Demo</title>
         <script type="text/javascript" src="lib/angular.min.js"></script>
         <script type="text/javascript" src="js/app.js"></script>
     </head>
     <body>
         <div ng-controller="SampleCtrl">
              Counter : {{counter}}<br/>
              <button ng-click="add()">Increase</button><br/>
              <button ng-click="minus()">Decrease</button>
         </div>
     </body>

</html>


再來是 SampleCtrl 的程式(js/app.js)



angular.module('sampleApp', [])
     .controller("SampleCtrl", function($scope){
         $scope.counter = 1;
        
         $scope.add = function(){
             $scope.counter++;
         };
    
         $scope.minus = function(){
             $scope.counter--;
         };

});

接下來就可以開始對 Controller 進行測試,測試的目地就不再提了

很重要的一點就是要描述 Spec,以我們的範例部外乎就是

當執行 add 函式時 counter 的值要加1,而執行 minus 函式時 counter 要減1

接下來看一下 karma.conf.js


module.exports = function(config) {
     config.set({
      basePath: '',
      frameworks: ['jasmine'],
      /*
       * 加載所需的js檔到瀏覽器中
       * 除了需要將要被測試程式與測試程式加入之外
       * 也須將 angularjs library(angular.min.js)以及
       * angular-mocks.js 加載進去
       * */
      files: [
        'lib/angular.min.js',
        'lib/angular-mocks.js',
        'js/*.js',
        'qa/*.js'
      ],
      exclude: [
      ],
      preprocessors: {
      },
      reporters: ['progress'],
      port: 9876,
      colors: true,
      logLevel: config.LOG_INFO,
      autoWatch: true,
      browsers: ['Chrome'],
      singleRun: false
     });

};

需要注意的是我們要將 angular-mocks.js 加載到瀏覽器中

angular-mocks.js 簡單來說就是提供了 AngularJS 很多的 Mock Object

它能夠替換掉你的某些重要元件,讓你在測試的時候可以先當作該元件已經實做好了

也能夠讓你再測試時更專注於目前的測試程式上

例如你的 Controller 可能會用 Ajax 向後端取得資料,在測試的時候就可以用 Mock Object

來取代你的 Ajax 元件,讓你的測試程式就算在 Ajax 的元件沒有完成的情況下,依舊可以正常運作

回歸到我們的 Controller 測試,以下列出測試程式(qa/controller-test.js)

describe("Controller Test", function(){
     var mockScope = {};
     var controller = null;

     //Loading our module 'sampleApp'
     beforeEach(angular.mock.module("sampleApp"));

     //Using angular.mock.inject to resolve dependency
     beforeEach(angular.mock.inject(function($controller, $rootScope){
         //create a mock scope object by $rootScope
         mockScope = $rootScope.$new();
         //create a controller object by $controller
         controller = $controller("SampleCtrl", {
              $scope: mockScope
         });
     }));

     it("The Counter initial value should be 1", function(){
         expect(mockScope.counter).toEqual(1);
     });

     it("Increase counter, result will be 2", function(){
         mockScope.add();
         expect(mockScope.counter).toEqual(2);;
     });

     it("Decrease counter, result will be 0", function(){
         mockScope.minus();
         expect(mockScope.counter).toEqual(0);;
     });
});

最後在 command line 執行 $karma start karma.conf.js

就會看到以下結果了



沒有留言:

張貼留言