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

h2s*_*ein 7 javascript unit-testing jasmine

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

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

    // change someArray in arbitrary ways
    someArray.splice( 2 );
    ...
}
Run Code Online (Sandbox Code Playgroud)

现在,我想验证是否使用正确的数组内容调用回调.使用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 ] );
    });
});
Run Code Online (Sandbox Code Playgroud)

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

我该如何测试这样的代码?

use*_*143 3

Jasmine 会浅复制传递arguments给间谍的对象,这意味着该arguments对象将引用与调用它的对象相同的对象(在您的情况下, arguments将仅引用someArray对象。

间谍实现的 Jasmine 代码参考:

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

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

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