问题描述
好的,所以我在某个问题上遇到了很长时间,我想听听社区其他人的意见.
Alright, so I have been stumbling upon some issue for a long time and I would like to hear an opinion from the rest of community.
首先,让我们看一些抽象控制器.
First, let's look at some abstract controller.
function Ctrl($scope, anyService) {
$scope.field = "field";
$scope.whenClicked = function() {
util();
};
function util() {
anyService.doSmth();
}
}
显然我们在这里:
- 带有
$scope
和一些服务注入的控制器的常规脚手架 - 附加到作用域的一些字段和函数
- 私有方法
util()
- regular scaffold for controller with
$scope
and some service injected - some field and function attached to the scope
- private method
util()
现在,我想在单元测试(Jasmine)中介绍这个类.但是,问题是我想验证当我单击(调用 whenClicked()
)某些项目时,util()
方法将被调用.我不知道该怎么做,因为在 Jasmine 测试中,我总是收到错误,说明 util()
的模拟尚未定义或未调用.
Now, I'd like to cover this class in unit tests (Jasmine). However, the problem is that I want to verify that when I click (call whenClicked()
) some item that the util()
method will be called. I don't know how to do that, since in Jasmine tests I'm always getting errors that either the mock for util()
hasn't been defined or was not called.
注意:我不是要修复这个特定示例,我是在询问一般情况下测试此类代码模式.所以请不要告诉我什么是确切的错误".我问的是如何做到这一点,而不是如何解决这个问题.
我一直在尝试多种方法来解决这个问题:
I have been trying a number of ways around this:
- 显然我不能在我的单元测试中使用
$scope
因为我没有将此函数附加到这个对象(它通常以消息Expected spy but got undefined 结束
或类似) - 我尝试通过
Ctrl.util = util;
将这些函数附加到控制器对象,然后验证类似Ctrl.util = jasmine.createSpy()
的模拟,但在此caseCtrl.util
没有被调用所以测试失败 - 我尝试将
util()
更改为附加到this
对象并再次模拟Ctrl.util
,但没有运气
- obviously I cannot use
$scope
in my unit tests as I don't have this function attached to this object (it usually ends with messageExpected spy but got undefined
or similar) - I tried attaching those functions to the controller object via
Ctrl.util = util;
and then verifying mocks likeCtrl.util = jasmine.createSpy()
but in this caseCtrl.util
is not being called so tests fail - I tried to change
util()
to be attached tothis
object and mockingCtrl.util
again, with no luck
好吧,我找不到解决这个问题的方法,我希望 JS ninjas 能提供一些帮助,一个工作小提琴将是完美的.
Well, I cannot find my way around this, I would expect some help from JS ninjas, a working fiddle would be perfect.
推荐答案
在作用域上命名空间是污染.您想要做的是将该逻辑提取到一个单独的函数中,然后将其注入到您的控制器中.即
Namespacing it on the scope is pollution. What you want to do is extract that logic into a separate function which is then injected into your Controller. i.e.
function Ctrl($scope, util) {
$scope.field = "field";
$scope.whenClicked = function() {
util();
};
}
angular.module("foo", [])
.service("anyService", function(...){...})
.factory("util", function(anyService) {
return function() {
anyService.doSmth();
};
});
现在您可以使用模拟 Ctrl 以及util"进行单元测试.
Now you can unit test with mocks your Ctrl as well as "util".
这篇关于如何在 AngularJs 中使用私有方法编写可测试的控制器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!