DOM 操作
另一类通常被认为难以测试的函数是直接操作 DOM 的代码。让我们看看如何测试以下 jQuery 代码片段,该代码片段监听单击事件、异步获取一些数据并设置跨度的内容。
¥Another class of functions that is often considered difficult to test is code that directly manipulates the DOM. Let's see how we can test the following snippet of jQuery code that listens to a click event, fetches some data asynchronously and sets the content of a span.
'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__/
文件夹中创建一个测试文件:
¥Again, we create a test file in the __tests__/
folder:
'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
,以便我们的测试不会发送真正的网络请求,而是解析为本地模拟数据。这确保了我们的测试可以在毫秒而不是秒内完成,并保证快速的单元测试迭代速度。
¥We are mocking fetchCurrentUser.js
so that our test doesn't make a real network request but instead resolves to mock data locally. This ensures that our test can complete in milliseconds rather than seconds and guarantees a fast unit test iteration speed.
此外,正在测试的函数在 #button
DOM 元素上添加了一个事件监听器,因此我们需要为测试正确设置 DOM。jsdom
和 jest-environment-jsdom
包模拟 DOM 环境,就像你在浏览器中一样。这意味着我们调用的每个 DOM API 都可以以与在浏览器中观察相同的方式进行观察!
¥Also, the function being tested adds an event listener on the #button
DOM element, so we need to set up our DOM correctly for the test. jsdom
and the jest-environment-jsdom
package simulate a DOM environment as if you were in the browser. This means that every DOM API that we call can be observed in the same way it would be observed in a browser!
要开始使用 JSDOM 测试环境,必须安装 jest-environment-jsdom
软件包(如果尚未安装):
¥To get started with the JSDOM test environment, the jest-environment-jsdom
package must be installed if it's not already:
- npm
- Yarn
- pnpm
npm install --save-dev jest-environment-jsdom
yarn add --dev jest-environment-jsdom
pnpm add --save-dev jest-environment-jsdom
此示例的代码可在 examples/jquery 处获取。
¥The code for this example is available at examples/jquery.