如何在 AngularJs 中使用私有方法编写可测试的控制器? [英] How to write testable controllers with private methods in AngularJs?

查看:17
本文介绍了如何在 AngularJs 中使用私有方法编写可测试的控制器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,所以我在某个问题上遇到了很长时间,我想听听社区其他人的意见.

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() 的模拟,但在此case Ctrl.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 message Expected spy but got undefined or similar)
  • I tried attaching those functions to the controller object via Ctrl.util = util; and then verifying mocks like Ctrl.util = jasmine.createSpy() but in this case Ctrl.util is not being called so tests fail
  • I tried to change util() to be attached to this object and mocking Ctrl.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 中使用私有方法编写可测试的控制器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆