Jestjs 用Jest测试MutationObserver
我写了一个脚本,主要目的是向一些表的单元格中添加新元素 测试是这样做的:Jestjs 用Jest测试MutationObserver,jestjs,Jestjs,我写了一个脚本,主要目的是向一些表的单元格中添加新元素 测试是这样做的: document.body.innerHTML = ` <body> <div id="${containerID}"> <table> <tr id="meta-1"><td> </td></tr> <tr id="meta-2"><td> &
document.body.innerHTML = `
<body>
<div id="${containerID}">
<table>
<tr id="meta-1"><td> </td></tr>
<tr id="meta-2"><td> </td></tr>
<tr id="meta-3"><td> </td></tr>
<tr id="no-meta-1"><td> </td></tr>
</table>
</div>
</body>
`;
const element = document.querySelector(`#${containerID}`);
const subject = new WPMLCFInfoHelper(containerID);
subject.addInfo();
expect(mockWPMLCFInfoInit).toHaveBeenCalledTimes(3);
WPMLCFInfoHelper.addInfo
是mockWPMLCFInfoInit
的真实版本(当然,这是一种模拟方法)
根据上面的测试,如果添加类似的内容
const table = element.querySelector(`table`);
var row = table.insertRow(0);
console.log('New row added')代码>从不被调用。
当然,我也尝试在新行中添加所需的单元格
当然,手动测试告诉我代码是有效的
环顾四周,我的理解是,MutationObserver不受支持,也不受支持
很公平,但在这种情况下,我如何测试代码的这一部分?除了手动操作,即:)我知道我在这里参加聚会迟到了,但在我的jest设置文件中,我只是添加了以下mockMutationObserver
类
global.MutationObserver = class {
constructor(callback) {}
disconnect() {}
observe(element, initObject) {}
};
这显然不允许您测试观察者是否做了您想做的事情,但允许您的代码的其余测试运行,这是通向工作解决方案的路径 问题实际上出现了,因为JSDom不支持MutationObserver
,所以您必须提供适当的polyfill
小技巧的想法可能不是最好的解决方案(为了与IE9-10兼容,让我们使用library intential)
- 您可以采用类似于此的开源项目,它代表了类似的逻辑
- 导入到测试文件并使其成为全局
步骤1(将此库安装到devdependences)
步骤2(导入并使其成为全局)
为TypeScript用户添加:
通过添加名为:mutation-observer.d.ts的文件来声明模块
/// <reference path="../../node_modules/mutation-observer" />
declare module "mutation-observer";
您可以使用mutationobserver shim
将此添加到setup.js中
导入“mutationobserver shim”
安装
npm i -D mutationobserver-shim
我认为解决方案的相当一部分只是一种心态转变。单元测试不应确定MutationObserver
是否正常工作。假设它是,并模拟代码所利用的部分
只需提取回调函数,即可独立测试;然后,模拟MutationObserver(如中所示)以防止错误。将模拟列表传递给回调,并测试结果是否符合预期
也就是说,使用Jest mock函数模拟MutationObserver
及其observe()
和disconnect()
方法,至少可以检查已创建的MutationObserver
实例的数量,以及是否在预期时间调用了这些方法
const MutationObserver mock=jest.fn(函数MutationObserver(回调){
this.observe=jest.fn();
this.disconnect=jest.fn();
//(可选)添加trigger()方法以手动触发更改
this.trigger=(mockedMutationsList)=>{
回调(mockedMutationsList,this);
};
});
global.MutationObserver=MutationObserver-mock;
它('您的测试用例',()=>{
//在代码中调用新的MutationObserver()之后
expect(mutationObserverMock.mock.instances).toBe(1);
const[observer实例]=mutationobserver mock.mock.instances;
期望(observeInstance.observe).toHaveBeenCalledTimes(1);
});
因为这里没有提到:jsdom支持MutationObserver已有一段时间了
这是实现它的PR您需要创建一个模拟
MutationObserver
的实现,它可以按照您需要的方式运行。@AlexRobertson模拟对于导入的模块来说不是问题,但我不知道如何模拟定义为MutationObserver=window.MutationObserver | | window.webkit MutationObserver代码>这就是我学会如何处理它们的方法。记住,这不会测试突变观察者的东西。我仍然没有找到一个很好的解决方案,所以我的代码中的变异观察者部分仍然很可怕。你可以使用Jest mock函数来模拟MutationObserver
。这允许您在代码中测试它的实例。请看一个例子。出于某种原因,这对我不起作用。我必须在测试文件中定义它,这真的很痛苦。这看起来正是我想要的!除了在我的设置中,它没有任何效果。我收到错误“[BootstrapVue warn]:observeDom:需要MutationObserver支持。”使用jest、BootstrapVue、vue test utils执行vue单元测试。任何进一步的提示都会非常棒。@Rodhaward虽然我无法说明BootstrapVue可能会发生什么,但我的示例是在一个使用vue test utils的vue cli项目中使用的。不过,我们在自己的代码中手动使用了MutationObserver。BootstrapVue有一个hasMutationObserverSupport
签入。我最好的猜测是,它与它位于节点单元模块中有关,jest是如何处理的?这对我来说很有用。谢谢。
import MutationObserver from 'mutation-observer'
global.MutationObserver = MutationObserver
test('your test case', () => {
...
})
/// <reference path="../../node_modules/mutation-observer" />
declare module "mutation-observer";
import MutationObserver from 'mutation-observer'
(global as any).MutationObserver = MutationObserver
npm i -D mutationobserver-shim