2013-11-04 57 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