2014-09-18 57 views
3

我的項目使用的是AngularJS + Kendo-UI。我試圖測試使用一個劍道的UI網我的控制器之一:使用Kendo Grid/Datasource的單元測試Angular Controller

angular.module('myApp')('DevicesCtrl', function ($scope) { 

    $scope.gridOptions = { 
     dataSource: { 
      transport: { 
       read: { 
        url: "/devices", 
        dataType: "json" 
       } 
      }, 
      change: function(){ 
       var view = this.view(); 
       $scope.devices = []; 

       $.each(view, function(i, v) { 
        $scope.devices.push({id: v.id, description: v.name, status: v.status == 0 ? "failure" : "success"}); 
       }); 
       $scope.$apply(); 
      } 
     }, 
     columns: [ 
      { 
       field: "name", 
       title: "Name", 
       width: 250, 
       template: function (item) { 
        var itemStatus = item.status == 0 ? 'failure' : 'success'; 
        return '<div label size="small" operation="' + itemStatus + '" label="' + item.name + '"></div>'; 
       } 
      }, 
      { 
       field: "status", 
       title: "Status" 
      } 
     ] 
    }; 
}); 

當我寫我的單元測試,我預計,GET請求會被稱爲:

describe('deviceCtrl', function() { 

    var scope, deviceCtrl, httpBackend, timeout; 

    beforeEach(module("myApp")); 
    beforeEach(module('src/modules/devices/views/device.html')); 

    beforeEach(inject(function ($controller, $rootScope, $httpBackend, $timeout, $state) { 
     scope = $rootScope.$new(); 

     httpBackend = $httpBackend; 
     timeout = $timeout; 

     httpBackend.expectGET('languages/en_US.json').respond({}); 

     deviceCtrl = $controller("DeviceCtrl", { 
      $scope: scope 
     }); 

     $state.go("devices"); 
     timeout.flush() 

    })); 

    it('should load the switch list', function() { 

     httpBackend.expectGET("/devices").respond(
      [{"id":"1","name":"name 1","status":"1"}, 
      {"id":"2","name":"name 2","status":"2"}] 
     ); 

     httpBackend.flush(); 

    }); 

}); 

但期望永遠不會滿足,不會有任何要求。 所以我的問題是:有沒有辦法讓Kendo Grid/Datasource來打這個電話,所以我可以嘲笑它?

我看到了一些關於如何使用Mockjax(http://www.telerik.com/forums/best-practice-mocking-with-datasource)的示例,但我更願意使用角庫來實現這一點。

回答

6

經過大量的研究,我可以找到一些方法來測試使用Kendo數據源的控制器。

Kendo有自己的方法來使Ajax調用來獲取數據,並且不使用常規的Angular $ http來做到這一點,所以使用Angular工具(angular-mocks)來測試有點棘手。 讓我們轉到以下選項:

1 - 使用常規的Angular方式執行Ajax調用。

劍道讓我們改變它獲取數據的方法,所以不是這樣做的:

dataSource: new kendo.data.DataSource({ 
      transport: { 
       read: { 
        url: "/devices, 
        dataType: "json" 
       } 
      }, 
      change: function(){ 
       var view = this.view(); 
       $scope.devices = []; 

       $.each(view, function(i, v) { 
        $scope.devices.push({id: v.id, description: v.name, status: v.status == 0 ? "failure" : "success"}); 
       }); 
       $scope.$apply(); 
      } 
     }); 

我們將改變爲:

dataSource: new kendo.data.DataSource({ 
      transport: { 
       read: function(options){ 
        $http.get("/devices").then(function(response){ 
         options.success(response.data); 
         $scope.devices = []; 
         response.data.forEach(function(v){ 
          $scope.devices.push({id: v.id, description: v.name, status: v.status == 0 ? "failure" : "success"}); 
         }); 
        }); 
       } 
      } 
     }); 

然後我們可以使用常規的$ httpBackend.expectGET(URL )來模擬Ajax調用。 我個人喜歡這種方法,因爲我們有更多的控制權。 Ps .:使用函數內的變量「options」,我們可以訪問網格過濾器,排序和分頁值。

2 - 模擬Kendo Ajax調用。

通過這種方式,我們在Controller上幾乎沒有任何變化,唯一需要改變的是使用新的kendo.data.DataSource({})創建新的數據源,而不是僅傳遞選項。 這需要這樣做,因爲我們在測試用例中調用了讀取函數。 我嘗試了不同的方法來模擬這個Ajax請求,但唯一能讓它工作的是使用名爲Jasmine-Ajax的工具。 而在測試情況下,我們寫的東西,如:

var request = jasmine.Ajax.requests.mostRecent(); 
request.response(MockData); 

我希望這可以幫助其他人。