断言观察到事件

问题描述 投票:4回答:2

如何在QUnit测试用例中声明观察到特定的Backbone事件?

该应用程序使用Backbone.js events(Backbone.js版本1.3.3)进行组件之间的通信。通过在事件总线上触发自定义事件,简单视图响应按钮单击:

// foo.js

const WheelView = Backbone.View.extend({

    events: {
        "click #btn-spin-wheel": "onSpinButtonClick",
    },

    onSpinButtonClick: function () {
        console.log("DEBUG: clicked #btn-spin-wheel");
        Backbone.trigger("wheel:spin");
    },
});

我想要一个QUnit测试用例(QUnit版本1.22.0)断言“当选择此按钮时,事件”foo“出现在事件总线上”。

测试用例还需要知道事件的其他方面(例如可选参数),因此我需要在测试用例中定义的函数,测试用例将其排列为特定事件的回调。

这是我尝试过的最新测试用例,通过为事件回调制作一个Sinon(版本1.9.0)间谍函数:

// test-foo.js

QUnit.module("Button “btn-spin-wheel”", {
    beforeEach: function (assert) {
        this.wheelView = new WheelView();
    },
    afterEach: function (assert) {
        delete this.wheelView;
    },
});

QUnit.test(
    "Should observe the “wheel:spin” event.",
    function (assert) {
        assert.expect(1);

        const spinWheelButton = document.querySelector(
            "#qunit-fixture #btn-spin-wheel");
        const eventListener = sinon.spy(function () {
            console.log("DEBUG:QUnit: received ‘wheel:spin’ event");
        });
        Backbone.once("wheel:spin", eventListener);

        const done = assert.async();
        window.setTimeout(function () {
            spinWheelButton.click();
            window.setTimeout(function () {
                assert.ok(eventListener.calledOnce);
            }.bind(this));
            done();
        }.bind(this), 500);
    });

console.log调用是为了帮助我了解哪些函数被调用,哪些函数不被调用。我希望看到两者:

DEBUG: clicked #btn-spin-wheel
DEBUG:QUnit: received ‘wheel:spin’ event

而是仅显示单击消息:

DEBUG: clicked #btn-spin-wheel

这是因为测试用例失败了:

Button “btn-spin-wheel”: Should observe the “wheel:spin” event. (3, 0, 3)    579 ms
    1.  Assertion after the final `assert.async` was resolved    @ 578 ms
        Source: Assert.prototype.ok@file:///usr/share/javascript/qunit/qunit.js:1481:3

    2.  failed, expected argument to be truthy, was: false    @ 578 ms
        Expected: true
        Result: false
        Source: @file://[…]/test-foo.html:50:29

    3.  Expected 1 assertions, but 2 were run    @ 579 ms
        Source: @file://[…]/test-foo.html:36:13

Source: @file://[…]/test-foo.html:36:13

我已阅读有关QUnit support for asynchronous testing的内容,我正在尝试使用不同的assert.asyncsetTimeout用法,如文档示例中所示。到目前为止它无济于事。

我应该如何使用QUnit,Sinon和Backbone来断言(来自应用程序的特定观察事件的存在和特定属性)?

javascript unit-testing sinon qunit backbone-events
2个回答
0
投票

您应该能够为您的活动注册一个监听器并使用assert.async来监听它,如下所示:

var done = assert.async();
Backbone.once("wheel:spin", function(event) {
    done();
});

const spinWheelButton = document.querySelector("#qunit-fixture #btn-spin-wheel");
spinWheelButton.click();

由于setTimeout调用,可能只是因为您的代码没有按预期运行。

Here你可以找到有关QUnit的async的更多文档。


0
投票

问题是测试用例之间的相互作用。测试用例操纵侦听器并将事件触发到事件中心;但是所有测试用例共享同一个事件中心。

因此,当测试用例异步运行时,而不是隔离测试用例,在一个测试用例中触发的事件可能会影响另一个。

我实现的解决方法是每个测试用例的自定义事件队列,在QUnit.module.beforeEach….afterEach中进行管理:

/**
 * Set up an event hub fixture during `testCase`.
 *
 * @param testCase: The QUnit test case during which the fixture
 * should be active.
 * @param eventHub: The Backbone.Events object on which the fixture
 * should exist.
 */
setUpEventsFixture: function (testCase, eventHub) {
    testCase.eventHubPrevious = eventHub._events;
    eventHub._events = [];
},

/**
 * Tear down an event hub fixture for `testCase`.
 *
 * @param testCase: The QUnit test case during which the fixture
 * should be active.
 * @param eventHub: The Backbone.Events object on which the fixture
 * should exist.
 */
tearDownEventsFixture: function (testCase, eventHub) {
    eventHub._events = testCase.eventHubPrevious;
},

通过在测试模块定义中使用这些:

QUnit.module("Button “btn-spin-wheel”", {
    beforeEach: function (assert) {
        setUpEventsFixture(this, Backbone);
        this.wheelView = new WheelView();
    },
    afterEach: function (assert) {
        delete this.wheelView;
        tearDownEventsFixture(this, Backbone);
    },
});

现在,测试用例可以继续使用使用公共Backbone对象作为事件中心的代码,但它们的事件彼此隔离。

© www.soinside.com 2019 - 2024. All rights reserved.