1

我在这里有一些交互的东西,它们交互得不好。

我有一个基类:

    var ObjOne = (function() {
        return function() {
            var self = this;
            self.propertyOne = ko.observable(1);
            self.observable = ko.observable(1);

            self.observable.subscribe(function(newValue) {
                self.propertyOne(newValue);
            });
        };
    } ());

它有两个 Knockout observables,并在其中一个上定义了一个更新另一个的订阅。

我有一个“子类”,用 jQuery.extend 扩展:

    var ObjTwo = (function() {
        return function() {
            this.base = new ObjOne();
            $.extend(this, this.base);
        };
    } ());

我有一个 Jasmine 测试,它试图问一个问题“当我更新 observable 时,是否调用了 propertyOne?”

it('Test fails to call the correct propertyOne', function() {
    var obj = new ObjTwo();
    spyOn(obj, 'propertyOne').andCallThrough();

    obj.observable(2);

    expect(obj.propertyOne).toHaveBeenCalled();
    expect(obj.propertyOne()).toBe(2);
});

这失败了“预期的间谍 propertyOne 已被调用。”。当我调试时,observable 会正确更新。在实际系统中,它工作正常(同样,甚至测试“propertyOne 是否等于 2?”通过。当我调试订阅函数时,self.propertyOne 不是间谍,但在测试中,它是。

我有一个解决方案,但不是很好:

 it('Test calls the base propertyOne', function() {
    var obj = new ObjTwo();
    spyOn(obj.base, 'propertyOne').andCallThrough();

    obj.observable(2);

    expect(obj.base.propertyOne).toHaveBeenCalled();
    expect(obj.propertyOne()).toBe(2);
});

请注意添加到这两行的.base 。我不喜欢我必须公开基类,或者必须触摸它的属性才能使测试运行。

这是一个 jsfiddle:http: //jsfiddle.net/4DrrW/23/。问题是 - 有没有更好的方法来做到这一点?

4

1 回答 1

2

调用$.extend(this, this.base);您的对象后,基本上如下所示:

{
    base: {
        propertyOne: ko.observable(1),
        observable: ko.observable(1)
    },
    propertyOne: base.propertyOne,
    observable: base.observable
}

当您执行 a spyOnforpropertyOne时,它会用包装器替换它。但是,订阅是在实际的 observables 之间设置的,并且无法调用包装器。

如果您不想访问base,那么我将删除调用 observable 的测试。检查该值是否正确似乎就足够了。

否则,您最好ObjOne通过使用新对象调用其构造函数来混合,this如下所示:

var ObjTwo = (function() {
    return function() {
        ObjOne.call(this);
    };
} ());

然后,测试就可以了:http: //jsfiddle.net/rniemeyer/z2GU3/

于 2012-11-23T03:57:11.697 回答