如何在Jasmine.js中使用带有toHaveBeenCalledWith的间谍和一个可变数组?

时间:2012-10-18 22:50:42

标签: javascript unit-testing jasmine

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

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也会失败。可变对象也会出现同样的问题。

如何测试此类代码?

2 个答案:

答案 0 :(得分:1)

Jasmine对传递给间谍的arguments进行浅层复制,这意味着arguments对象将引用与其相同的对象(在您的情况下为arguments}将只引用someArray对象。

间谍实施的Jasmine代码参考:

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

数组的深层副本(arguments)不可作为通用解决方案,问题在link解释。

您的问题的解决方案可能是为您的特定用例编写自己的回调和匹配器,在那里您可以确切知道要复制(克隆)的内容。

答案 1 :(得分:0)

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