簡體   English   中英

使用Angular.js + UI路由器進行Karma測試

[英]Karma Testing with Angular.js + UI Router

我想知道如何使用Angular.js + UI路由器進行Karma測試?

我定義了以下狀態:哪個有兩個解析器來獲取一些數據並為控制器准備數據。 (來自Ember背景,這很有道理。)

$stateProvider
  .state('users', {
    resolve: {
      getData: function (User) {
        return User.query().$promise
      },
      stateModels: function (getData) {
        var models = {}
        models.users = getData
        return models
      }
    },
    url: '/',
    templateUrl: '/views/users/index.html',
    controller: 'UsersIndexCtrl'
  })

我們的UserIndexCtrl看起來像:(它接受已解析的stateModels並將其分配給$ scope,因此視圖可以使用它)

app.controller('UsersIndexCtrl', [
  '$scope', '$state', 'stateModels',
  function ($scope, $state, stateModels) {

    $scope.users = stateModels.users

  }])

這在瀏覽器中運行良好,我看到了正確的結果。 但是,當涉及到測試時,它給了我奇怪的錯誤。

以下是Karma單元測試的示例:

describe('controllers', function () {

  var $httpBackend
    , $rootScope
    , $scope
    , $state
    , $httpBackend
    , $controller

  beforeEach(module('app'))

  beforeEach(inject(function ($injector) {
    $state = $injector.get('$state')
    $rootScope = $injector.get('$rootScope')
    $httpBackend = $injector.get('$httpBackend')
    $scope = $rootScope.$new()
    $controller = $injector.get('$controller')
  }))

  it('UserIndexCtrl should exist', inject(function () {
    $httpBackend
      .expect('GET', '/api/users')
      .respond(200, {users: [ {}, {}, {} ]})

    $state.go('users')
    $rootScope.$apply()

    $controller('AdminZonesIndexCtrl', { $scope: $scope, $state: $state });
    $rootScope.$apply()
    assert.equal($scope.users.length, 3)
  }))

})

而且我看到:

[$injector:unpr] Unknown provider: stateModelsProvider <- stateModels
http://errors.angularjs.org/1.3.0-build.2937+sha.4adc44a/$injector/unpr?p0=stateModelsProvider%20%3C-%20stateModels
Error: [$injector:unpr] Unknown provider: stateModelsProvider <- stateModels
http://errors.angularjs.org/1.3.0-build.2937+sha.4adc44a/$injector/unpr?p0=stateModelsProvider%20%3C-%20stateModels

這里的想法是:

  • 我們模擬出API請求,以便對/ api / users的GET請求將返回3個對象的數組。
  • 我們去名為users的州
  • 我們希望看到$ scope.users應該是一個包含3個對象的數組。
  • 通過此測試,我們測試了路由器中定義的兩個解析,以及控制器正確分配了已解析的對象。

謝謝比爾

出現錯誤的原因是您首先轉換到使用新作用域實例化UsersIndexCtrl的狀態,然后在測試中創建另一個控制器實例(同樣,使用新作用域)。 這兩者是彼此獨立的,在第二種情況下, stateModels是未知/不可用的依賴。

因此,雖然您的想法是有效的測試問題,但在嘗試將所有三個一起斷言時,您實際上是在單元測試環境中執行端到端測試。 你不應該這樣做 - 這樣做會產生一種脆弱的依賴:

  • 屬於“用戶”狀態的控制器
  • 在狀態轉換的某個地方調用特定的http請求
  • stateModels依賴項綁定到范圍。

在這些斷言中,只有最后一個與控制器有任何關系。 控制器的單元測試不關心實例化的方式/時間或stateModels依賴關系的來源,它們只關心控制器自身的行為。 那么,讓我們分開這個行為:

單元測試控制器

您的第一次測試應該減少到以下幾點:

it('binds the users to the scope', function(){
   var stateModels = [{}, {}, {}];
   $controller('UserIndexCtrl', {$scope: $scope, stateModels: stateModels});
   assert.equal($scope.users, stateModels);
});

請注意,在添加更多測試時,您可能希望將控制器實例化移動到beforeEach塊。

測試路線

測試路徑的關注點實際上是應用程序行為的問題,您應該遵循Protractor 但是,如果您特別想對狀態執行單元測試,則最好通過測試狀態本身的配置來實現。 例如:

it('resolves the stateModels dependency', function() {
   var state = $state.get('users');
   assert.isDefined(state.resolve.stateModels); 
   // perform assertion that stateModels function resolves to what is expected
   // Note: any such assertion should stub any dependency being used, to ensure
   // we are testing in isolation.
});

盡管如此,我個人並不選擇單元測試路由/路由配置,而是通過使用Protractor的e2e測試獲得此類覆蓋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM