如何在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.async
和setTimeout
用法,如文档示例中所示。到目前为止它无济于事。
我应该如何使用QUnit,Sinon和Backbone来从应用程序中声明特定观察事件的存在性和特定属性?
答案 0 :(得分: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
的更多文档。
答案 1 :(得分: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
对象作为事件中心的代码,但它们的事件彼此隔离。