【发布时间】:2014-02-08 11:50:35
【问题描述】:
我正在为一个控制器编写一个单元测试,该控制器启动 $modal 并使用返回的承诺来执行一些逻辑。我可以测试触发 $modal 的父控制器,但我一生都无法弄清楚如何模拟一个成功的承诺。
我尝试了很多方法,包括使用$q 和$scope.$apply() 来强制解决promise。但是,我得到的最接近的是将类似于 this SO 帖子中最后一个答案的内容放在一起;
我见过几次用“旧”$dialog 模态询问这个问题。
我找不到太多关于如何使用“新”$dialog 模态来做到这一点。
一些指针将不胜感激。
为了说明问题,我使用了example provided in the UI Bootstrap docs,并进行了一些小的修改。
控制器(主要和模式)
'use strict';
angular.module('angularUiModalApp')
.controller('MainCtrl', function($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.open = function() {
$scope.modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
resolve: {
items: function() {
return $scope.items;
}
}
});
$scope.modalInstance.result.then(function(selectedItem) {
$scope.selected = selectedItem;
}, function() {
$log.info('Modal dismissed at: ' + new Date());
});
};
})
.controller('ModalInstanceCtrl', function($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function() {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
});
视图 (main.html)
<div ng-controller="MainCtrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3>I is a modal!</h3>
</div>
<div class="modal-body">
<ul>
<li ng-repeat="item in items">
<a ng-click="selected.item = item">{{ item }}</a>
</li>
</ul>
Selected: <b>{{ selected.item }}</b>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
<button class="btn btn-default" ng-click="open()">Open me!</button>
<div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
测试
'use strict';
describe('Controller: MainCtrl', function() {
// load the controller's module
beforeEach(module('angularUiModalApp'));
var MainCtrl,
scope;
var fakeModal = {
open: function() {
return {
result: {
then: function(callback) {
callback("item1");
}
}
};
}
};
beforeEach(inject(function($modal) {
spyOn($modal, 'open').andReturn(fakeModal);
}));
// Initialize the controller and a mock scope
beforeEach(inject(function($controller, $rootScope, _$modal_) {
scope = $rootScope.$new();
MainCtrl = $controller('MainCtrl', {
$scope: scope,
$modal: _$modal_
});
}));
it('should show success when modal login returns success response', function() {
expect(scope.items).toEqual(['item1', 'item2', 'item3']);
// Mock out the modal closing, resolving with a selected item, say 1
scope.open(); // Open the modal
scope.modalInstance.close('item1');
expect(scope.selected).toEqual('item1');
// No dice (scope.selected) is not defined according to Jasmine.
});
});
【问题讨论】:
-
嗨,如果我想测试 modalInstance 控制器(在本例中为 ModalInstanceCtrl),最好的方法是什么?
-
Itsak:我把你的评论变成了一个完整的问题。我也坚持这一点。问题在这里:stackoverflow.com/q/24373220/736963
-
我的 5 cents with jasmine >= 2 你应该使用 spyOn($modal, 'open').and.callFake(fakeModal);
标签: unit-testing angularjs angular-ui-bootstrap