编辑:快速&这篇文章末尾的脏解决方案
我正在使用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的控制器实例化中的范围模拟方法,我想出了如何“解决”我的问题,但它可能非常脏,所以如果你找到更好的方法,请随意评论我打算做什么。
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 () {
it('should instantiate the controller properly', function () {
expect(Ctrl).not.toBeUndefined();
});
it('should initialize its values properly', function () {
});
});
});
这样,Jasmine不再搜索提供程序,因为您已经注入了应该需要这些提供程序的项目。它有效,但我相信它可以以更好的方式完成......
答案 0 :(得分:63)
我通过创建模拟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对象有任何依赖,而且我们的单元测试很好并且是孤立的。
答案 1 :(得分:6)
而不是:
modalInstance = { // Create a mock object using spies
close: jasmine.createSpy('modalInstance.close'),
dismiss: jasmine.createSpy('modalInstance.dismiss'),
result: {
then: jasmine.createSpy('modalInstance.result.then')
}
};
这可以写成:
modalInstance = jasmine.createSpyObj('modalInstance', ['close', 'dismiss', 'result.then']);
此外没有$ modalInstance现在是$ uibModalInstance所以上面的每个“modalInstance”都应该替换为“uibModalInstance”
答案 2 :(得分:2)
+1为fiznool的回答。这是正确的,应该选择..
我想注意一件事,它在这里呈现的方式是不可维护的。
由于这是有角度的,我建议使用它..
angular.module('...').service('$modalInstance', function(){
... define spies and such
})
会使您的代码更加模块化和通用化。
只需使用上述内容在spec
某处添加文件,并确保将其包含在karma.conf
如果您想确保仅在特定测试中加载,只需为其指定一个唯一的模块名称,并将其添加到module
beforeEach
调用中