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设置文件中,我只是添加了以下mock
MutationObserver

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