在JsTestDriver中测试手动触发的事件

时间:2011-07-05 17:53:19

标签: javascript unit-testing prototypejs js-test-driver

测试对象中事件处理的最佳方法是什么?我似乎无法想出这个。

我有一个设置一些事件侦听器的对象,当它观察这些事件被触发时,它会更改页面上的dom对象。当我进行多次测试时,下面示例中的最后一个测试失败,如果我注释掉其他测试就没问题。

我有一个看起来像

的测试套件
var TitleTest = TestCase('TitleTest');

TitleTest.prototype.defaultTitle = 'title';
TitleTest.prototype.defaultCount = '0';

TitleTest.prototype.setUp = function() {
    var titleObj;
    this.div = new Element('div');
    $$('body').first().insert(this.div);
    this.div.insert('<div id="title"><h1><span id="titleCaption">' + this.defaultTitle + '</span><span id="titleCount">' + this.defaultCount + '</span></h1></div>');
    titleObj = new Title();
});

TitleTest.prototype.testNewItemsEvent = function() {
    var data = {count: 10};

    assertEquals('Count should be zero before events are fired', this.defaultCount, $('titleCount').innerHTML);
    document.fire('custom:NewItems', data);
    assertEquals('New count should be 10', data.count + '', $('titleCount').innerHTML);
});

// ... a few other simple tests like the one above

TitleTest.prototype.testUpdateSpecial = function() {
    var data = {caption: 'Special Title', count: 10},
        specialObj = {special: {type: 2, value: 5}};

    // Emulate a special type of category, that can only be 
    // added at page load
    document.fire('custom:UpdateTitle', data);
    assertEquals(data.caption, $('titleCaption').innerHTML);
    assertEquals(data.count, $('titleCount').innerHTML);

    //Removing the special category should revert the title to its default
    document.fire('custom:RemoveSpecial', specialObj);
    assertEquals(this.defaultTitle, $('titleCaption').innerHTML);
    assertEquals(this.defaultCount, $('titleCount').innerHTML);

    // only way to get this added back in during non load is using
    // javascript history so it needs to revert to previous state
    document.fire('custom:AddSpecial', specialObj);
    assertEquals(data.caption, $('titleCaption').innerHTML);
    assertEquals(data.count + '', $('titleCount').innerHTML);
});

如果之前的测试运行,最后一对断言将始终失败,但如果我注释掉其他测试,则会通过。我无法做我能做的工作。

编辑:这是处理添加/删除特殊标题的代码

    Event.observe(document, 'custom:UpdateTitle', function(event) {
        if (event.memo.caption) {
            this._updateCaption(event.memo.caption);
        }

        if (event.memo.count) {
            this._updateCount(event.memo.count);
        }   

    }.bind(this));


    Event.observe(document, 'custom:RemoveSpecial', function(event) {
        if (
            event.memo.special.type === 1 ||
            event.memo.special.type === 2 ||
            (   
                event.memo.special.type === 3 &&
                parseInt(event.memo.special.value, 10) === 8
            )   
        ){  
            this._previousTitle = $('titleCaption').innerHTML;
            this._resetTitle();
        }   
    }.bind(this));

    Event.observe(document, 'custom:AddSpecial', function(event) {
        if (
            event.memo.special.type === 1 ||
            event.memo.special.type === 2 ||
            (   
                event.memo.special.type === 3 &&
                parseInt(event.memo.special.value, 10) === 8
            )   
        ){  
            if (!this._previousTitle.blank()) {
                this._updateCaption(this._previousTitle);
            }   
        }   
    }.bind(this));

2 个答案:

答案 0 :(得分:1)

尝试在tearDown方法中编写一些清理代码,以从title中分离titleObj及其侦听器。据我所知,jsTestDriver在每次测试后重置DOM,但我不确定侦听DOM事件的对象会发生什么。你可能仍然有一个旧的titleObj,不能被垃圾收集,因为它附加到DOM。

除此之外,测试DOM事件的方式看起来很好。触发DOM事件并断言代码是否符合预期......

答案 1 :(得分:1)

@meyertee暗示我的问题的解决方案。我假设setup和teardown像PHPUnit一样工作,它们分别在所有测试运行之前和之后被触发,但是jsTestDriver在每次测试之前和之后触发它们。由于我在设置中设置了DOM和Title事件,因此在每次测试之前都会创建一个新的标题对象,因此会有更多的侦听器导致竞争条件。我将我的Title对象的实例化移出了设置,这解决了这个问题。