![](/img/trans.png)
[英]Angular.js promise not resolving when unit testing service with 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
這里的想法是:
謝謝比爾
出現錯誤的原因是您首先轉換到使用新作用域實例化UsersIndexCtrl
的狀態,然后在測試中創建另一個控制器實例(同樣,使用新作用域)。 這兩者是彼此獨立的,在第二種情況下, 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.