Pertanyaan Tegaskan bahwa suatu peristiwa telah diamati


Bagaimana saya bisa menegaskan, dalam kasus uji QUnit, bahwa peristiwa Backbone spesifik diamati?

Aplikasi ini menggunakan Peristiwa Backbone.js (Backbone.js versi 1.3.3) untuk berkomunikasi antar komponen. Tampilan sederhana menanggapi klik tombol, dengan memicu acara khusus di bus acara:

// 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");
    },
});

aku ingin sebuah QUnit test case (QUnit versi 1.22.0) yang menegaskan "ketika tombol ini dipilih, event" foo "muncul di event bus".

Test case juga perlu mengetahui aspek lain dari event (seperti argumen opsional), jadi saya memerlukan fungsi didefinisikan dalam ujian bahwa test case mengatur sebagai panggilan balik untuk acara tertentu.

Ini adalah uji coba terbaru yang saya coba, dengan membuat fungsi mata-mata Sinon (versi 1.9.0) untuk callback acara:

// 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);
    });

Itu console.log panggilan untuk membantu saya memahami fungsi mana yang dipanggil dan mana yang tidak. Saya berharap untuk melihat keduanya:

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

Sebagai gantinya, hanya pesan klik yang muncul:

DEBUG: clicked #btn-spin-wheel

Ini dikonfirmasi karena test case gagal:

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

Saya telah membaca tentang Dukungan QUnit untuk pengujian asinkron dan saya bereksperimen dengan yang berbeda assert.async dan setTimeout penggunaan, seperti yang disarankan dalam contoh dokumentasi. Sejauh ini tidak ada hasilnya.

Bagaimana seharusnya saya menggunakan QUnit, Sinon, dan Backbone, untuk menegaskan (keberadaan, dan sifat khusus) dari peristiwa yang diamati spesifik dari aplikasi?


4
2017-12-18 23:53


asal


Jawaban:


Anda harus dapat mendaftarkan pendengar untuk acara dan penggunaan Anda assert.async untuk mendengarkannya, sesuatu seperti ini:

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

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

Mungkin saja kode Anda tidak berperilaku seperti yang Anda harapkan karena setTimeout panggilan.

Sini Anda dapat menemukan dokumentasi lebih lanjut untuk QUnit async.


0
2017-12-19 09:09



Masalahnya ternyata menjadi interaksi antara uji kasus. Kasus uji memanipulasi pendengar dan acara kebakaran ke pusat acara; tetapi semua kasus uji berbagi sama hub acara.

Jadi ketika kasus uji berjalan secara asynchronous, bukannya kasus pengujian yang terisolasi, kejadian yang dipicu dalam satu dapat mempengaruhi yang lain.

Solusi yang telah saya terapkan adalah antrian acara kustom untuk setiap test case, yang dikelola dalam QUnit.module.beforeEach dan ….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;
},

Dengan menggunakan ini dalam definisi modul uji:

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);
    },
});

Kasus uji sekarang dapat terus menggunakan kode yang menggunakan umum Backbone objek sebagai hub acara, tetapi acara mereka terisolasi satu sama lain.


0
2017-12-20 18:49