12

我有一些代码以数组作为单个参数调用回调函数。调用回调后,代码更改数组内容。它类似于此代码:

function myCode( callback ) {
    var someArray = [ 1, 2, 3, 4 ];
    callback( someArray );

    // change someArray in arbitrary ways
    someArray.splice( 2 );
    ...
}

现在,我想验证是否使用正确的数组内容调用了回调。使用 Jasmine.js 我会这样写我的规范:

describe( "My code", function() {
    var callback;

    beforeEach( function() {
        callback = jasmine.createSpy( "My callback" );
        myCode( callback );
    });

    it( "calls the callback and passes the correct array", function() {
        expect( callback ).toHaveBeenCalledWith( [ 1, 2, 3, 4 ] );
    });
});

这失败了。问题是,Jasmine.js 记录了数组但没有复制它。由于调用后数组发生了变化,因此 expect()-Line 失败,即使实际调用满足了期望。可变对象也会出现同样的问题。

我怎样才能测试这样的代码?

4

2 回答 2

2

argumentsJasmine 确实将传递给间谍的浅拷贝,这意味着该arguments对象将引用与它被调用的相同对象(在您的情况下 argumentssomeArray仅引用 object.

spy 实现的 Jasmine 代码参考:

  spy = function() {
    callTracker.track({
      object: this,
      args: Array.prototype.slice.apply(arguments)
    });
    return spyStrategy.exec.apply(this, arguments);
  };

数组 () 的深拷贝arguments不可能作为通用解决方案,问题在链接中进行了解释。

您的问题的解决方案可能是为您的特定用例编写自己的回调和匹配器,您知道您必须准确复制(克隆)什么。

于 2014-01-20T13:27:07.960 回答
0

有时如果你的单元测试很难正确,它告诉你代码需要更加统一,并且可能有一些方法有太多的责任。看起来myCode正在做一些不同的事情:应用callback到某个数组,然后修改该数组。也许修改数组的代码可以提取到它自己的myCode调用方法中。然后,您可以简单地在单元测试中删除该额外方法,以确保使用正确的参数调用回调。

于 2012-10-19T03:47:17.540 回答