在 Jest 中测试 XMLHttpRequest onload() 回调功能
Posted
技术标签:
【中文标题】在 Jest 中测试 XMLHttpRequest onload() 回调功能【英文标题】:Testing XMLHttpRequest onload() callback functionality in Jest 【发布时间】:2022-01-20 02:30:55 【问题描述】:我正在使用 Jest 测试一些纯 html 和 vanilla javascript,并且希望能够模拟 XMLHttpRequest,但我定义的 onload()
回调函数除外。
我找到了一些如何模拟整个 XMLHttpRequest 的示例,但我希望能够模拟除我在代码中定义的 onload 函数之外的所有内容(这就是我要测试的逻辑) .
我想测试的 javascript 函数如下所示:
function foo()
document.getElementById("loading").style.display = "block";
var request = new XMLHttpRequest();
request.open('POST', '/expected/url', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send();
request.onload = function ()
if (request.status === 200)
var array = JSON.parse(request.responseText);
array.forEach(function (object)
// do some stuff
);
document.getElementById("loading").style.display = "none";
else
document.getElementById("loading").style.display = "none";
;
;
module.exports =
foo
我的测试文件看起来像:
var script = require('../fs/script.js');
const fs = require('fs');
const path = require('path');
const html = fs.readFileSync(path.resolve(__dirname, '../fs/index.html'), 'utf8');
const createMockXHR = responseJSON =>
const mockXHR =
open: jest.fn(),
send: jest.fn(),
setRequestHeader: jest.fn(),
status: 200,
readyState: 4,
;
return mockXHR;
;
describe('Foo', function ()
const oldXMLHttpRequest = window.XMLHttpRequest;
let mockXHR = null;
beforeEach(() =>
document.documentElement.innerHTML = html.toString();
mockXHR = createMockXHR();
window.XMLHttpRequest = jest.fn(() => mockXHR);
);
afterEach(() =>
window.XMLHttpRequest = oldXMLHttpRequest;
jest.resetModules();
);
it('is set, section is collapsed', function ()
mockXHR.response = ' "data": "point"';
var bar = document.getElementById("bar");
var elementToCollapse = bar.nextElementSibling;
script.foo();
expect(mockXHR.send).toBeCalled();
expect(mockXHR.onload).toBeCalled();
// expect some more things
);
);
我知道上面的内容是错误的,因为 onload()
没有在我的模拟中的任何地方定义,但我发现的唯一可能会引发错误的碎屑:
const createMockXHR = responseJSON =>
const mockXHR =
open: jest.fn(),
send: jest.fn().mockImplementation(function ()
onload = this.onload.bind(this);
onerror = this.onerror.bind(this);
),
setRequestHeader: jest.fn(),
status: 200,
readyState: 4,
;
return mockXHR;
;
错误:
TypeError: Cannot read properties of undefined (reading 'bind')
12 | send: jest.fn().mockImplementation(function ()
> 13 | onload = this.onload.bind(this);
【问题讨论】:
【参考方案1】:虽然没有从技术上回答这个问题,但我已经解决了我无法测试 onload()
内联函数的问题,方法是将逻辑放在单独的函数中并测试:
function foo_logic(request)
// the logic
function foo()
document.getElementById("loading").style.display = "block";
var request = new XMLHttpRequest();
request.open('POST', '/expected/url', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send();
request.onload = function () foo_logic(request) ;
;
module.exports =
foo_logic,
foo
然后测试:
var script = require('../fs/script.js');
const fs = require('fs');
const path = require('path');
const html = fs.readFileSync(path.resolve(__dirname, '../fs/index.html'), 'utf8');
const createMockXHR = responseJSON =>
const mockXHR =
open: jest.fn(),
send: jest.fn(),
setRequestHeader: jest.fn(),
status: 200,
readyState: 4,
;
return mockXHR;
;
describe('Foo', function ()
const oldXMLHttpRequest = window.XMLHttpRequest;
let mockXHR = null;
beforeEach(() =>
document.documentElement.innerHTML = html.toString();
mockXHR = createMockXHR();
window.XMLHttpRequest = jest.fn(() => mockXHR);
);
afterEach(() =>
window.XMLHttpRequest = oldXMLHttpRequest;
jest.resetModules();
);
it('is set, section is collapsed', function ()
mockXHR.responseText = JSON.stringify(
data: "point"
);
var bar = document.getElementById("bar");
var elementToCollapse = bar.nextElementSibling;
script.foo_logic(mockXHR);
// expect some things about bar and elementToCollapse
);
);
【讨论】:
以上是关于在 Jest 中测试 XMLHttpRequest onload() 回调功能的主要内容,如果未能解决你的问题,请参考以下文章
在使用 jest 的 vue 测试中找不到模块“@jest/globals”