2013-11-04 189 views
1

我有問題寫我的控制器的單元測試,測試orderBy在元素表中。angularjs單元測試控制器orderBy

我有advert.html:

<body ng-app="motoAdsApp" ng-controller="AdvertsController"> 

    <form> 
    <label>Sort by</label> 
    <select ng-model="sortByCol" ng-options="s.name for s in sortByCols"> 
     <option value=""></option> 
    </select> 
    </form> 

    <br/> 

    <table border="1"> 
    <tr ng-repeat="advert in adverts| orderBy:sortByCol.key"> 
     <td> 
     <span>{{advert.countryName}}, {{advert.regionName}}</span> 
     </td> 
     <td>{{advert.brandName}}</td> 
     <td>{{advert.modelName}}</td> 
     <td>{{advert.year}}</td> 
     <td>{{advert.price}}</td> 
    </tr> 
    </table> 

</body> 

controllers.js:

var motoAdsApp = angular.module('motoAdsApp', []); 

motoAdsApp.controller('AdvertsController', ['$scope', function($scope) { 

    $scope.sortByCols = [{ 
    "key": "year", 
    "name": "Year" 
    }, { 
    "key": "price", 
    "name": "Price" 
    }]; 

    $scope.adverts = []; 
    var allAdverts = ADVERTS_RESPONSE; 

    $scope.filter = { 
    brandName: null, 
    modelName: null, 
    country: null, 
    region: null, 
    yearFrom: null, 
    yearTo: null 
    }; 

    $scope.$watch('filter', filterAdverts, true); 

    function filterAdverts() { 
    $scope.adverts = []; 
    angular.forEach(allAdverts, function(row) { 
     if (!$scope.filter.country) { 
     $scope.filter.region = null; 
     } 
     if ($scope.filter.brandName && $scope.filter.brandName !== row.brandName) { 
     return; 
     } 
     // ... 
     $scope.adverts.push(row); 
    }); 
    } 

} 
]); 

我的單元測試controllersSpec.js:

describe('MotoAds controllers', function() { 

    beforeEach(function() { 
    this.addMatchers({ 
     toEqualData: function(expected) { 
     return angular.equals(this.actual, expected); 
     } 
    }); 
    }); 

    beforeEach(module('motoAdsApp')); 

    describe('AdvertsController', function() { 
    var scope, ctrl, $httpBackend; 

    beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) { 
     $httpBackend = _$httpBackend_; 
     $httpBackend.expectGET('data/adverts.json').respond(ADVERTS_RESPONSE); 

     scope = $rootScope.$new(); 
     ctrl = $controller('AdvertsController', {$scope: scope}); 
    })); 

    it('should sort by year', function() { 
     $httpBackend.flush(); 

     scope.$apply(function() { 
     scope.sortByCol = { key: "year"}; 
     }); 

     var prevYear = 0; 
     for (var i = 0; i < scope.adverts.length; i++) { 
     var advert = scope.adverts[i]; 
     expect(advert.year).toBeGreaterThan(prevYear); 
     prevYear = advert.year; 
     } 
    });  

    }); 

}); 

運行我的測試中,我有這後:

Chrome 30.0.1599 (Windows Vista) MotoAds controllers AdvertsController should so 
rt by year FAILED 
     Expected 2010 to be greater than 2011. 
     Error: Expected 2010 to be greater than 2011. 
      at null.<anonymous> (D:/projects/motoads/test/unit/controllers 
Spec.js:147:29) 
     Expected 2009 to be greater than 2012. 
     Error: Expected 2009 to be greater than 2012. 

我認爲元素(廣告)沒有排序。爲什麼?我該做什麼?

Plunker example (without runnable test)

回答

4

orderBy濾波器,就像一個ng-repeat的元件上使用時,實際上不進行排序的陣列對象,它過濾。數組對象保持不變,但編譯器用於創建所有html的輸出數組已被修改。

所以你的$scope.adverts數組永遠不會改變。輸出到視圖的方式發生變化,但不是數組本身。

您的單元測試的這部分看起來更像是您將使用E2E測試進行測試的東西。控制器並不在乎如何顯示元素。這是更多的觀點的責任。控制器只關心數據是否從API中抓取,然後交給視圖。然後e2e測試可以實際掃描視圖並確保元素排序正確。

UPDATE:

如果你想叫orderBy過濾器在您的測試,你可以做,使用類似於下面的內容:

... 
var scope, ctrl, $httpBackend, orderByFilter; 
beforeEach(inject(function(_$httpBackend_, $rootScope, $controller, $filter) { 
    $httpBackend = _$httpBackend_; 
    $httpBackend.expectGET('data/adverts.json').respond(ADVERTS_RESPONSE); 
    orderByFilter = $filter('orderBy'); 
    scope = $rootScope.$new(); 
    ctrl = $controller('AdvertsController', {$scope: scope}); 
})); 
... 
it('should do something', function(){ 
    var sortedArray = orderByFilter(scope.adverts, scope.sortByCol.key); 
    // do something with the sorted array here 
}); 
... 

對於如何從訪問orderBy過濾器的文檔javascript被發現here

希望有所幫助。

+0

我不能到這個內部數組或直接在我的測試中調用orderBy嗎?這不可能? – lukpaw

+0

我添加了一個更新到我以前的回覆。讓我知道這是否有幫助。 – tennisgent

+0

我有錯誤:TypeError:無法讀取未定義的屬性'鍵'爲null。所以'ng-model =「sortByCol」'必須爲null,但我不知道爲什麼? – lukpaw