跳至主要内容
版本:29.7

DOM 操作

另一类经常被认为难以测试的函数是直接操作 DOM 的代码。让我们看看如何测试以下监听点击事件、异步获取一些数据并设置 span 内容的 jQuery 代码片段。

displayUser.js
'use strict';

const $ = require('jquery');
const fetchCurrentUser = require('./fetchCurrentUser.js');

$('#button').click(() => {
fetchCurrentUser(user => {
const loggedText = 'Logged ' + (user.loggedIn ? 'In' : 'Out');
$('#username').text(user.fullName + ' - ' + loggedText);
});
});

同样,我们在 __tests__/ 文件夹中创建一个测试文件

__tests__/displayUser-test.js
'use strict';

jest.mock('../fetchCurrentUser');

test('displays a user after a click', () => {
// Set up our document body
document.body.innerHTML =
'<div>' +
' <span id="username" />' +
' <button id="button" />' +
'</div>';

// This module has a side-effect
require('../displayUser');

const $ = require('jquery');
const fetchCurrentUser = require('../fetchCurrentUser');

// Tell the fetchCurrentUser mock function to automatically invoke
// its callback with some data
fetchCurrentUser.mockImplementation(cb => {
cb({
fullName: 'Johnny Cash',
loggedIn: true,
});
});

// Use jquery to emulate a click on our button
$('#button').click();

// Assert that the fetchCurrentUser function was called, and that the
// #username span's inner text was updated as we'd expect it to.
expect(fetchCurrentUser).toHaveBeenCalled();
expect($('#username').text()).toBe('Johnny Cash - Logged In');
});

我们正在模拟 fetchCurrentUser.js,以便我们的测试不会发出真实的网络请求,而是解析为本地模拟数据。这确保了我们的测试可以在毫秒而不是秒内完成,并保证了快速的单元测试迭代速度。

此外,被测试的函数在 #button DOM 元素上添加了一个事件监听器,因此我们需要为测试正确设置 DOM。jsdomjest-environment-jsdom 包模拟了 DOM 环境,就像你在浏览器中一样。这意味着我们可以像在浏览器中观察到的那样观察我们调用的每个 DOM API!

要开始使用 JSDOM 测试环境,如果尚未安装,则必须安装 jest-environment-jsdom

npm install --save-dev jest-environment-jsdom

此示例的代码可在 examples/jquery 中找到。