2014年11月1日 星期六

AngularJS 教學 - Mocking a service

在前一篇  AngularJS 教學 - Service 測試 有簡單介紹到如何對 Service 進行測試

另外因為 Controller 常常需要依賴一些 Service Object 來做一些邏輯處理或後端的溝通

因此也說明了運用了 $injector 來將 Service Object 注入到 Controller,以利 Controller 的測試


不過有時候在開發的過程中,常常會遇到我們所開發的元件中所相依的元件還沒開發完成或是是別人的工作

例如我在開發某個 Controller 元件的時候,可能需要依賴很多的 Service

但這些 Service 可能尚未完成等等之類的因素,但為了確保我的 Controller 能夠如期完成並政常運作

先用模擬的方式來模擬這些 Service ,讓我的開發與測試能夠順利完成

而這些被模擬的東西我們可以稱為 mock object 或是 fake object

所以本篇會說明如何利用 $provide 來建立一個 mock 的 Service object

假設在 SampleCtrl 中我們需要依賴一個 TodoService

angular.module('sampleApp', [])
     .controller("SampleCtrl", function($scope, TodoService){
     $scope.todos = TodoService.getTodos();
 });



並且 TodoService 在還沒有被完成的情況下,那們我們該如何讓我們的 Controller 測試能夠通過

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

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

     beforeEach(angular.mock.module(function($provide){
         //Create a mock service object
         mockService = {
              getTodos: function(){
                  //Return some mock data you expected
                  return [
                       {id:1, name: 'Todo item1'},
                       {id:2, name: 'Todo item2'}
                  ];
              }
         };
         //Using $provide service to register a component with the $injector
         $provide.value("TodoService", mockService);
     }));

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


     it("Should get two Todo items from mock service", function(){
         expect(mockScope.todos.length).toEqual(2);
     });

});

從上面的測試程式可以看到,在第二個 beforeEach 中

我自己建立了一個 mock 的 service object,並且包含一個 getTodos 的方法

方法內會回傳我所期待的 mock data

完成之後再透過 $provide 的 value 方法將完成的 mock service 註冊名為 TodoService 的 Service

所以我們就可以透過 $injector 來取得 TodoService 了

之後再介紹利用 Jasmine 的 spy 的方式也可以達到 mocking 的效果!



沒有留言:

張貼留言