测试 JQuery 的 "on" 方法触发回调函数
Testing JQuery's "on" method fires callback function
我正在尝试使用 Jasmine 测试以下代码:
import $ from 'jquery';
export function createCheckIcon (handleClick) {
return $('<span>').attr('data-element', 'check').addClass('icon--check').on('click', handleClick);
}
export function createCrossIcon (handleClick) {
return $('<span>').attr('data-element', 'cross').addClass('icon--cross').on('click', handleClick);
}
我的测试是这样的:
import $ from 'jquery';
import { createCrossIcon, createCheckIcon } from './input-icons';
describe('input icons', () => {
let handleMock = { handleClick: () => true };
it('can create a cross icon', () => {
let $crossIcon = createCrossIcon();
expect($crossIcon).toHaveAttr('data-element', 'cross');
expect($crossIcon).toHaveClass('icon--cross');
});
it('cross icon handles click event', () => {
let $crossIcon = createCrossIcon(handleMock.handleClick);
spyOn(handleMock, 'handleClick');
$crossIcon.trigger('click');
expect(handleMock.handleClick).toHaveBeenCalled();
});
it('can create a check icon', () => {
let $checkIcon = createCheckIcon();
expect($checkIcon).toHaveAttr('data-element', 'check');
expect($checkIcon).toHaveClass('icon--check');
});
});
不幸的是,我的测试将失败:
Expected spy handleClick to have been called.
也许我仍然对如何测试点击手柄是否被触发有一个基本的误解。有人看到我的问题在哪里吗?我也试过 jasmine-jquery 来让它工作,但仍然没有运气。
问题
您对变量在 JavaScript 中的工作方式有误解。
你看,当你在 createCrossIcon(handleMock.handleClick)
中传递 handleClick
您实际上是将 link 传递给函数,而不是函数本身。然后将此 link 传递给 .on
方法。
然后你设置一个 Jasmine 间谍 - spyOn(handleMock, 'handleClick')
发生的事情是 Jasmine 将 handleMock
对象的 handleClick
属性 替换为一个始终记住的实用函数它被称为。
但是jQuery永远不会知道你的意图,因为它已经决定在点击时调用原始函数。
解决方案
您需要做的只是更改行的顺序,以便 spyOn
出现在 之前 创建图标:
spyOn(handleMock, 'handleClick');
let $crossIcon = createCrossIcon(handleMock.handleClick);
这样您将传递一个间谍作为回调,而不是实际的回调函数。
我正在尝试使用 Jasmine 测试以下代码:
import $ from 'jquery';
export function createCheckIcon (handleClick) {
return $('<span>').attr('data-element', 'check').addClass('icon--check').on('click', handleClick);
}
export function createCrossIcon (handleClick) {
return $('<span>').attr('data-element', 'cross').addClass('icon--cross').on('click', handleClick);
}
我的测试是这样的:
import $ from 'jquery';
import { createCrossIcon, createCheckIcon } from './input-icons';
describe('input icons', () => {
let handleMock = { handleClick: () => true };
it('can create a cross icon', () => {
let $crossIcon = createCrossIcon();
expect($crossIcon).toHaveAttr('data-element', 'cross');
expect($crossIcon).toHaveClass('icon--cross');
});
it('cross icon handles click event', () => {
let $crossIcon = createCrossIcon(handleMock.handleClick);
spyOn(handleMock, 'handleClick');
$crossIcon.trigger('click');
expect(handleMock.handleClick).toHaveBeenCalled();
});
it('can create a check icon', () => {
let $checkIcon = createCheckIcon();
expect($checkIcon).toHaveAttr('data-element', 'check');
expect($checkIcon).toHaveClass('icon--check');
});
});
不幸的是,我的测试将失败:
Expected spy handleClick to have been called.
也许我仍然对如何测试点击手柄是否被触发有一个基本的误解。有人看到我的问题在哪里吗?我也试过 jasmine-jquery 来让它工作,但仍然没有运气。
问题
您对变量在 JavaScript 中的工作方式有误解。
你看,当你在 createCrossIcon(handleMock.handleClick)
中传递 handleClick
您实际上是将 link 传递给函数,而不是函数本身。然后将此 link 传递给 .on
方法。
然后你设置一个 Jasmine 间谍 - spyOn(handleMock, 'handleClick')
发生的事情是 Jasmine 将 handleMock
对象的 handleClick
属性 替换为一个始终记住的实用函数它被称为。
但是jQuery永远不会知道你的意图,因为它已经决定在点击时调用原始函数。
解决方案
您需要做的只是更改行的顺序,以便 spyOn
出现在 之前 创建图标:
spyOn(handleMock, 'handleClick');
let $crossIcon = createCrossIcon(handleMock.handleClick);
这样您将传递一个间谍作为回调,而不是实际的回调函数。