编辑:本文末尾的“快速与肮脏”解决方案
我使用的是AngularUI-Bootstrap中的模式窗口,其方式与网站上说明的相同,只是我分割了文件。因此,我有:
CallingController.js:
$scope.delete = function () { if ($scope.selected.length > 0) { // [...] // preparing data // [...] var modalInstance = $modal.open({ templateUrl: 'views/modalView.html', controller: 'modalCtrl', resolve: { itemArray: function () { return $scope.selected; } } }); modalInstance.result.then(function (confirm) { if (confirm === true) { // [...] // treat // [...] } }); } };
modalController.js:
myAppControllers.controller('modalCtrl', function ($scope, $modalInstance, itemArray) { $scope.accept = function () { $modalInstance.close(true); }; $scope.reject = function () { $modalInstance.close(false); }; $scope.itemArray = itemArray; });
当我使用Karma测试此代码(在karma配置文件中加载了 ui-bootstrap-tpls.min.js 文件)时,出现以下错误: 错误:[$ injector:unpr] [ http:// errors。 angularjs.org/1.2.15-build.2389+sha.c5f2f58/ $ injector / unpr?p0 =%24modalInstanceProvider%20%3C-%20%24modalInstance] 1错误(本机),表示茉莉花无法管理查找$ modalInstance的提供程序。
我什至没有在此控制器上测试东西,但这是我的茉莉花测试文件:
testModalController.js:
describe('Controller: modalCtrl', function () { beforeEach(module('myApp')); var Ctrl; var scope; // Initialize the controller and a mock scope beforeEach(inject( function ($controller, $rootScope) { scope = $rootScope.$new(); Ctrl = $controller('modalCtrl', { $scope: scope }); }) ); describe('Initial state', function () { it('should instantiate the controller properly', function () { expect(Ctrl).not.toBeUndefined(); }); it('should initialize its values properly', function () { }); }); });
您对此问题有任何线索吗?它不是我使用(和测试)的第一个“外部”模块,并且我做了与其他模块相同的工作,只是这次不起作用,我也不知道为什么。
=========================================
编辑:快速且可能是肮脏的解决方案:
好的,因此基于Jasmine控制器实例化中的范围模拟方法,我弄清楚了如何“解决”我的问题,但是它可能很脏,因此,如果您找到一种更好的方式来实现我的意图,请随时发表评论。
describe('Controller: modalCtrl', function () { beforeEach(module('myApp')); var Ctrl; var scope; var modalInstance; // Initialize the controller and a mock scope beforeEach(inject( function ($controller, $rootScope, _$modal_) { scope = $rootScope.$new(); modalInstance = _$modal_.open({ templateUrl: 'views/modalView.html' }); Ctrl = $controller('modalCtrl', { $scope: scope, $modalInstance: modalInstance, itemArray: function () { return ['a', 'b', 'c']; } }); }) ); describe('Initial state', function () { it('should instantiate the controller properly', function () { expect(Ctrl).not.toBeUndefined(); }); it('should initialize its values properly', function () { }); }); });
这样,Jasmine不再搜索提供程序,因为您已经注入了本来需要这些提供程序的项目。它有效,但是我相信可以用更好的方法来完成…
我通过创建模拟modal和modalInstance对象并验证它们已被我的控制器代码调用来解决此问题。由于modal并且modalInstance是第三方库的一部分,因此测试它们是否可以正常工作不是我们的责任- 而是测试调用该库的代码是否可以正常工作是我们的责任。
modal
modalInstance
使用您的示例:
describe('Controller: modalCtrl', function () { beforeEach(module('myApp')); var Ctrl; var scope; var modalInstance; // Initialize the controller and a mock scope beforeEach(inject( function ($controller, $rootScope) { // Don't bother injecting a 'real' modal scope = $rootScope.$new(); modalInstance = { // Create a mock object using spies close: jasmine.createSpy('modalInstance.close'), dismiss: jasmine.createSpy('modalInstance.dismiss'), result: { then: jasmine.createSpy('modalInstance.result.then') } }; Ctrl = $controller('modalCtrl', { $scope: scope, $modalInstance: modalInstance, itemArray: function () { return ['a', 'b', 'c']; } }); }) ); describe('Initial state', function () { it('should instantiate the controller properly', function () { expect(Ctrl).not.toBeUndefined(); }); it('should close the modal with result "true" when accepted', function () { scope.accept(); expect(modalInstance.close).toHaveBeenCalledWith(true); }); it('should close the modal with result "false" when rejected', function () { scope.reject(); expect(modalInstance.close).toHaveBeenCalledWith(false); }); }); });
这样,我们实际上就不需要对Angular-UI对象有任何依赖,并且我们的单元测试是很好且独立的。