【问题标题】:Function inside of for loop not being tested未测试 for 循环内的函数
【发布时间】:2017-08-01 10:38:14
【问题描述】:

我有一个正在尝试测试的函数:

  vm.clearArray = function(){
    for (var id=0; id<vm.copyArray.length;id++){
      vm.styleIcon(vm.copyArray[id],'black')
    }
    vm.copyObjArray = [];
    vm.copyArray = [];
  }

我正在尝试像这样测试它:

it('should have cleared copyArray on function call', function(){

    var ctrl = $componentController('copy', null);

    spyOn(ctrl, 'clearArray').and.callThrough();
    spyOn(ctrl, 'styleIcon').and.callThrough();

    ctrl.copyArray = [123];
    ctrl.clearArray();

    expect(ctrl.clearArray).toHaveBeenCalled();
    // expect(ctrl.styleIcon).toHaveBeenCalled();
    expect(ctrl.copyObjArray).toEqual([]);
    expect(ctrl.copyArray).toEqual([]);
  });

如果我取消对上述预期的注释,我会收到一个错误,并且 vm.styleIcon 调用从未包含在我的覆盖率报告中。通过将 copyArray 设置为在数组中包含一个值,我认为 for 循环会在运行测试时触发。好像不是这样的。

谢谢。

【问题讨论】:

  • 你必须spyOnstyleIcon()函数吗?
  • 是的@Pointy,如果我在其中添加它仍然失败。
  • 在循环内设置断点并检查指令是否被调用。
  • 我不确定,但请尝试移动 ctrl.copyArray = [123];就在 var ctrl = $componentController('copy', null); 之后

标签: javascript unit-testing karma-jasmine


【解决方案1】:

我相信有某种继承方案会导致您的错误。我的假设是您的控制器由基本控制器扩展

从我看到的少数代码中,我可以做出两个假设:

1) clearArray() 在子控制器中被覆盖,例如。

vm.clearArray = function(){
    ...
    vm.copyArray = [];
}

所以你正在尝试测试错误的 clearArray()

2) ctrl.copyArray 是不可写的,因为继承的实现方式,例如。

function ParentController() {
    var vm = this;
    vm.copyArray = [];
    vm.copyObjArray = [];
    vm.clearArray = function() {
        for (var id=0; id<vm.copyArray.length;id++){
            vm.styleIcon(vm.copyArray[id],'black')
        }
        vm.copyObjArray = [];
        vm.copyArray = [];
    }

    vm.styleIcon = function(index, color) {
    }
};

function ChildController() {
    ParentController.call(this);
}

ChildController.prototype = Object.create(ParentController.prototype, {copyArray:{ value: [] } });

var ctrl = new ChildController();

使用上面会报错,copyArray被定义为不可写属性,所以行:

ctrl.copyArray = [123];

不改变其值。

无论如何,如果没有更多的代码,很难得到导致错误的原因。

【讨论】:

    【解决方案2】:

    很难确定确切原因,因为您展示的是直接从测试中提取的样本,而不是minimal, complete, and verifiable example。此外,您没有指定错误或expect 结果是什么,因此我们提供的信息非常有限。

    也就是说,我强烈怀疑vm 是未定义/空或不是可通过$componentController 实例化的原型。如果是这种情况,您应该在spyOn(ctrl, 'clearArray').and.callThrough()ctrl.clearArray() 收到错误,永远不会运行循环,因此永远不会调用vm.styleIcon。在这种情况下,您需要验证 ctrl 实际上是任何原型 vm 的一个实例(它实际上是一个全局变量吗?)。

    如果不是这种情况并且vm 原型是正确的并且$componentController('copy', null); 正在创建您认为的对象,则可能styleIcon 未定义/为空,无法调用并创建基本相同的问题.在这种情况下,请确保设置了 styleIcon 并且它是您认为的函数。

    当一切都失败时,调试器就是你的朋友。

    请指定错误是什么以及它们发生的位置(更详细地)以获得更好的答案。

    【讨论】:

      【解决方案3】:

      循环的代码看起来不错,所以我认为属性vm.copyArray可能根本没有设置。如果添加console.log(vm.copyArray),结果是什么?

      也许vm和$componentController('copy', null)不是对同一个对象的引用,而是通过某个库互相调用对方的函数?有没有其他方法可以从测试脚本中引用vm,而不是使用$componentController('copy', null)

      当您将函数中的数组作为参数传递时,您的循环必须被触发。当然,除非在实际代码中将 vm.copyArray 作为参数传递,否则您的实际代码将失败,但它会告诉您是否是循环问题,或者测试脚本中对 vm 的引用:

      //tested function
       vm.clearArray = function(copyArray){
          for (var id=0; id<copyArray.length;id++){
            vm.styleIcon(copyArray[id],'black')
          }
        }
      
      //test
      ctrl.clearArray([123]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-21
        • 2018-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-07
        相关资源
        最近更新 更多