1

我正在寻找测试我的函数对另一个函数的调用,特别是作为对象的参数。

问题是 sinon.js 似乎存储了对其参数数组中给出的对象参数的引用,这自然是意料之中的。但是,这会在稍后由 ref 修改参数时产生问题,这会在调用函数时更改这些参数的表观值。

对这种情况进行单元测试的最佳方法是什么?

这是一个人为的例子:

http://jsfiddle.net/xtfQu/

var view = Backbone.View.extend({
    initialize: function () {
        _.bindAll(this);    
    },

    dostuff: function () {
        var coords = { x: 0, y: 0 };
        for (var i = 0; i < 10; i++) {
            this.otherstuff(coords);

            coords.x += 10;
        }
    },

    otherstuff: function (coord) {
        // Stubbed
    }
});

test("a test", function() {
    // Arrange
    var blah = new view();

    sinon.stub(blah, 'otherstuff');

    // Act
    blah.dostuff();

    // Assert
    var expectedFirstCallCoords = { x: 0, y: 0 };

    // All assertions on the value of x for a particular call would seem to be impossible.
    // blah.otherstuff.firstCall.args[0].x --> 100
    deepEqual(blah.otherstuff.firstCall.args[0], expectedFirstCallCoords, 'parameter changed by ref, untestable?');
});​

我可以想到围绕这个“问题”的各种技巧。有没有一种更简洁的方法,不涉及克隆对象或仅仅为了让 sinon 工作而修改我的生产代码?

4

1 回答 1

7

感谢 Mantoni 在Github上对此的相关讨论:

var param = { property: 'value' };
var engage = sinon.stub();
var engageWithValue = engage.withArgs(sinon.match({ property : 'value' }));

engage(param);

param.property = 'new value';

sinon.assert.calledOnce(engageWithValue); // passes
于 2012-10-16T14:09:20.420 回答