2014年10月30日 星期四

AngularJS 教學 - Service 測試

本偏簡單介紹該如何測試 Service,並說明該如何在測試中解決依賴注入的問題(Dependency Injection)

如果不太清楚 AngularJS 的測試,可以看 http://programer-learn.blogspot.com/2014/10/angularjs-unit-testing.html

以下是本次範例的頁面,在 Text Box 輸入名子,按下 Button 後,Text Box 的值就會改變












接下來看一下原始碼 (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">
              Name:<input type="text" ng-model="name"/>
              <br/><button ng-click="echo()">Echo</button>
         </div>
     </body>

</html>



再來看定義 Controller 以及 Service 的程式 (js/app.js)

angular.module('sampleApp', [])
   .controller("SampleCtrl", function($scope, SampleService){
     $scope.name = "";

     $scope.echo = function(){
         $scope.name = SampleService.echo($scope.name);
     };
   }).factory("SampleService", function(){
       return {
           echo: function(name){
               return "Hello " + name;
           }
       };

   });

上面的程式都相當容易,接著主要就要來看測試的部分

首先是  Karma 的設定檔 (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
 });

};

接著我們先來看如何對 SampleService 進行單元測試(qa/service-test.js)

describe("Controller Test", function(){
     var mockService;

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

     // mock service object
     beforeEach(angular.mock.inject(function($injector){
          // using $injector retrieve object instances as defined by provider                      mockService = $injector.get("SampleService");
     }));

     it("The echo function should return 'Hello {name}'", function(){
         var name = "Allen";
         expect(mockService.echo(name)).toEqual("Hello "+name);
     });

});

最後則是 Controller 的測試,同樣的因為 Controller 會將我們定義的 SampleService 注入

所以在測試的時候同樣可以用 $injector 來取得一個 mock 的 service 物件,

並透過 $controller 的 constructor 注入給 Controller 物件(qa/controller-test.js)

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

     beforeEach(angular.mock.module("sampleApp"));

     beforeEach(angular.mock.inject(function($controller, $rootScope, $injector){
         mockScope = $rootScope.$new();
         controller = $controller("SampleCtrl", {
              $scope: mockScope,
              SampleService: $injector.get("SampleService")
         });
     }));


     it("he echo function should return 'Hello {name}'", function(){
         var name = "Allen";
         mockScope.name = name;
         mockScope.echo(name);
         expect(mockScope.name).toEqual("Hello "+name);
     });

});

最後透過 $karma start karma.conf.js 來進行測試

沒有留言:

張貼留言