编辑:快速&在这篇文章结尾的脏解决方案
我使用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 = $ modalInstanceProvider < - $ modalInstance] 1在错误(本机),意味着jasmine不设法找到$ 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控制器实例化的范围模拟方法,我想出了如何“解决”我的问题,但它可能很脏,所以随意评论,如果你找到一个更好的方式来做我想要的。
testModalController.js:
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 () { }); }); });
这样,Jasmine不再搜索提供程序,因为您已经注入了应该需要这些提供程序的项目。它工作,但我相信它可以做一个更好的方式…
我解决这个只是创建模拟模态和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,'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对象,我们的单元测试是好的和孤立的。