如何在 Jasmine 中对 $uibModal 进行单元测试? (单元测试注入库)
How to unit test $uibModal in Jasmine? (unit testing injected library)
所以我正在使用 bootstrap 的 $uibModal 并且我的 AngularJS 控制器中有以下代码:
vm.openPopup = function() {
$uibModal.open({
templateUrl: 'popup.html',
controller: function() {
var modal = this;
modal.hi = function() {
// some code here
}
}
});
};
我将如何调用 Jasmine 中的 modal.hi 函数并对其进行单元测试以确保其正常工作?
所以测试这段代码的主要问题是你基本上 "buried" 一个匿名函数 (modal.hi
) 在 另一个 匿名函数 ( $uibModal.open
)。这使得测试非常棘手。
您有几个选择:a.) 您可以模拟 $uibModal
服务,b.) 您可以重组代码,或者 c.) 您可以放弃 hi
在 vm
本身上运行,然后从您的测试中调用它。我认为最后一个选项是最方便的,但这里是所有三种方法的一些示例。
选项 1:模拟 $uibModal
服务
describe('Test vm.openPopup', function () {
var mockUibModal = {
open: function(options){
var ctrl = options.controller();
// call your `hi` function:
ctrl.hi();
}
};
beforeEach(function(){
module(function($provide){
$provide.value('$uibModal', mockUibModal);
});
});
});
从那里,您可以调用 vm.openPopup
方法,然后开始测试结果。注意 module
函数来自 angular-mocks, which you'll need to install/include with your tests. Related question: "How do you mock a service in AngularJS when unit testing with jasmine?"
选项 2:重组代码
这是我经常使用的模式,它涉及将您希望测试的 logic/functions 转移到一个单独的工厂中:
var app = angular.controller('YourController', function ($uibModal, MyHelperFactory) {
var vm = this;
var modal;
var helper = MyHelperFactory(vm, modal);
vm.openPopup = function () {
$uibModal.open({
templateUrl: 'popup.html',
controller: function () {
modal = this;
modal.hi = helper.hi;
}
});
};
});
app.factory('MyHelperFactory', function () {
return function (vm, modal) {
return {
hi: function () {
// some code here, maybe it needs to reference the `vm` object, whatever...
}
}
};
})
这种方法的好处是您可以单独测试 MyHelperFactory
,而不需要实例化 YourController
,也不需要涉及 $uibModal
服务。这通常是我最喜欢的方法:没有 inline/anonymous 函数 - 将逻辑放入辅助工厂,并从我的控制器中取出。
选项 3:将 hi
函数拖放到 vm
var app = angular.controller('YourController', function ($uibModal, MyHelperFactory) {
var vm = this;
// this pattern allows your function to be scoped with the not-yet-existing `modal` object
vm.hi = function (modal) {
return function () {
// some code here
}
};
vm.openPopup = function () {
$uibModal.open({
templateUrl: 'popup.html',
controller: function () {
var modal = this;
modal.hi = vm.hi(modal);
}
});
};
});
然后,您可以通过在测试中调用 vm.hi
来测试它。我称这种方法为 "dirty" 是因为它将 hi
方法添加到 vm
对象,而且我通常会避免向 vm
对象添加任何实际不需要的属性控制器范围。但是在这种情况下,我们违反了该规则,因为这是 "expose" 您希望测试的此功能的 quickest/easiest 方式。
所以我正在使用 bootstrap 的 $uibModal 并且我的 AngularJS 控制器中有以下代码:
vm.openPopup = function() {
$uibModal.open({
templateUrl: 'popup.html',
controller: function() {
var modal = this;
modal.hi = function() {
// some code here
}
}
});
};
我将如何调用 Jasmine 中的 modal.hi 函数并对其进行单元测试以确保其正常工作?
所以测试这段代码的主要问题是你基本上 "buried" 一个匿名函数 (modal.hi
) 在 另一个 匿名函数 ( $uibModal.open
)。这使得测试非常棘手。
您有几个选择:a.) 您可以模拟 $uibModal
服务,b.) 您可以重组代码,或者 c.) 您可以放弃 hi
在 vm
本身上运行,然后从您的测试中调用它。我认为最后一个选项是最方便的,但这里是所有三种方法的一些示例。
选项 1:模拟 $uibModal
服务
describe('Test vm.openPopup', function () {
var mockUibModal = {
open: function(options){
var ctrl = options.controller();
// call your `hi` function:
ctrl.hi();
}
};
beforeEach(function(){
module(function($provide){
$provide.value('$uibModal', mockUibModal);
});
});
});
从那里,您可以调用 vm.openPopup
方法,然后开始测试结果。注意 module
函数来自 angular-mocks, which you'll need to install/include with your tests. Related question: "How do you mock a service in AngularJS when unit testing with jasmine?"
选项 2:重组代码
这是我经常使用的模式,它涉及将您希望测试的 logic/functions 转移到一个单独的工厂中:
var app = angular.controller('YourController', function ($uibModal, MyHelperFactory) {
var vm = this;
var modal;
var helper = MyHelperFactory(vm, modal);
vm.openPopup = function () {
$uibModal.open({
templateUrl: 'popup.html',
controller: function () {
modal = this;
modal.hi = helper.hi;
}
});
};
});
app.factory('MyHelperFactory', function () {
return function (vm, modal) {
return {
hi: function () {
// some code here, maybe it needs to reference the `vm` object, whatever...
}
}
};
})
这种方法的好处是您可以单独测试 MyHelperFactory
,而不需要实例化 YourController
,也不需要涉及 $uibModal
服务。这通常是我最喜欢的方法:没有 inline/anonymous 函数 - 将逻辑放入辅助工厂,并从我的控制器中取出。
选项 3:将 hi
函数拖放到 vm
var app = angular.controller('YourController', function ($uibModal, MyHelperFactory) {
var vm = this;
// this pattern allows your function to be scoped with the not-yet-existing `modal` object
vm.hi = function (modal) {
return function () {
// some code here
}
};
vm.openPopup = function () {
$uibModal.open({
templateUrl: 'popup.html',
controller: function () {
var modal = this;
modal.hi = vm.hi(modal);
}
});
};
});
然后,您可以通过在测试中调用 vm.hi
来测试它。我称这种方法为 "dirty" 是因为它将 hi
方法添加到 vm
对象,而且我通常会避免向 vm
对象添加任何实际不需要的属性控制器范围。但是在这种情况下,我们违反了该规则,因为这是 "expose" 您希望测试的此功能的 quickest/easiest 方式。