Javascript 测试模态控制器:未知提供程序:$modalInstanceProvider<;-$modalInstance,TypeError:试图分配给只读属性
我对AngularJs有点陌生。我使用AngularUI引导(0.10.0)进行模式实现。我在测试模态控制器时遇到以下错误Javascript 测试模态控制器:未知提供程序:$modalInstanceProvider<;-$modalInstance,TypeError:试图分配给只读属性,javascript,angularjs,angular-ui-bootstrap,angularjs-service,Javascript,Angularjs,Angular Ui Bootstrap,Angularjs Service,我对AngularJs有点陌生。我使用AngularUI引导(0.10.0)进行模式实现。我在测试模态控制器时遇到以下错误 使用AngularJs 1.2.7:TypeError:试图分配给只读属性 使用AngularJs 1.2.12:unknown provider:$modalInstanceProvider我也一直在与这个问题作斗争。问题在于,您试图在测试中实例化的控制器是完全不同的实例,$modal服务在内部实例化,并作为$modalInstance传递到实际的modal窗口中。请参见
使用AngularJs 1.2.7:TypeError:试图分配给只读属性
使用AngularJs 1.2.12:unknown provider:$modalInstanceProvider我也一直在与这个问题作斗争。问题在于,您试图在测试中实例化的控制器是完全不同的实例,$modal服务在内部实例化,并作为$modalInstance传递到实际的modal窗口中。请参见示例中的js代码注释: 那么,如何测试控制器呢?对不起,我还没有找到解决办法。不同之处在于,您无法访问控制器的作用域,因为$modal服务根据$rootScope或随选项传入的作用域创建新的作用域。所以你失去了方向
您至少可以测试传递给结果的函数。这是通过监视$modal.open函数并返回模拟来完成的。这里显示了这一点。并使用诸如量角器之类的工具补充集成测试。So。。这是测试它的一种方法
describe('Testing',function() {
it('test',function() {
inject(function($rootScope, $modal) {
var fakeModal = { };
//Basically, what you want is for your modal's controller to get
//initalized and then returned to you, so the methods in it can be unit tested
spyOn(modal, 'open').andReturn(fakeModal);
ctrl = $controller('Controller',
{
$scope : ctrlScope,
$modal: modal
});
});
});
});
请查看在以下问题上选择为正确的答案:
我在同一个问题上挣扎了一段时间,这个问题(和答案)帮助我以一种非常干净的方式测试我的模态(以及打开/关闭模态的函数) 我不喜欢这里给出的任何答案,因此我添加了我自己的答案 我不喜欢上面的答案的原因是,一旦一个项目大一点,它们就不起作用了 对我来说,解决方案就是简单地实现一个名为$modalInstance的角度服务 因此,在
spec
下,我创建了一个名为shimmes
的文件夹,用于这些小项目。(确保将其添加到karma.conf
)
在那里我实现了
angular.module(..).service('$modalInstance', function(){
this.dismiss = jasmine.createSpy('$modalInstance.dismiss');
...
});
我发现这种方法更简洁、更易于维护和直接
有时,我喜欢确保仅为特定测试加载垫片,在这种情况下,我只需给它一个特定的模块名,然后我必须为它添加一个模块
调用,否则它不会加载
我还强烈建议使用不同的modals库,出于许多原因,我建议使用ng-dialog,但在这种情况下,我可以说它对测试更加友好,已经使用了一段时间了 具有下一个模态控制器定义:
angular.module('module').controller('ModalInstanceController',ModalInstanceController);
function ModalInstanceController($timeout, $modalInstance, $scope) {
//controller across a bunch of modals
$scope.closeModal = function(){
$modalInstance.dismiss('cancel');
};
$scope.action = function(){
$modalInstance.dismiss();
};
}
您可以使用jasmine使用所需的方法创建spy对象,并在创建实例时将该对象传递给控制器:
beforeEach(inject(($controller, $timeout, $rootScope) => {
modalInstance = jasmine.createSpyObj('modalInstance', ['dismiss']);
scope = $rootScope.$new();
controller = $controller('ModalInstanceController', {
$modalInstance: modalInstance,
$scope: scope
});
}));
稍后在测试场景中,您可以检查spied对象:
it('should defined the required methods on the scope', () => {
expect(scope.closeModal).toBeDefined();
expect(scope.action).toBeDefined();
scope.closeModal();
expect(modalInstance.dismiss).toHaveBeenCalledWith('cancel');
scope.action();
expect(modalInstance.dismiss).toHaveBeenCalledWith();
});
此代码不起作用,模态未定义,测试仍然失败。
angular.module(..).service('$modalInstance', function(){
this.dismiss = jasmine.createSpy('$modalInstance.dismiss');
...
});
angular.module('module').controller('ModalInstanceController',ModalInstanceController);
function ModalInstanceController($timeout, $modalInstance, $scope) {
//controller across a bunch of modals
$scope.closeModal = function(){
$modalInstance.dismiss('cancel');
};
$scope.action = function(){
$modalInstance.dismiss();
};
}
beforeEach(inject(($controller, $timeout, $rootScope) => {
modalInstance = jasmine.createSpyObj('modalInstance', ['dismiss']);
scope = $rootScope.$new();
controller = $controller('ModalInstanceController', {
$modalInstance: modalInstance,
$scope: scope
});
}));
it('should defined the required methods on the scope', () => {
expect(scope.closeModal).toBeDefined();
expect(scope.action).toBeDefined();
scope.closeModal();
expect(modalInstance.dismiss).toHaveBeenCalledWith('cancel');
scope.action();
expect(modalInstance.dismiss).toHaveBeenCalledWith();
});