【问题标题】:How to mock window/document with mocha/chai如何使用 mocha/chai 模拟窗口/文档
【发布时间】:2016-07-29 18:48:15
【问题描述】:

当我尝试对 getElement 函数进行单元测试时

class BarFoo {
    getElement() {
        return document.querySelector('#barfoo');
    }
}

mocha 对document 一无所知,所以我想你可能会这样做:

beforeEach(() => {
    global.document = {
        querySelector: () => { ... }
    }
}

虽然这可行,但我想知道这是否是正确的方法,也许有一个包可以解决这个问题,因为如果使用更多的浏览器 API,我的方法会变得很费力?

【问题讨论】:

    标签: javascript node.js unit-testing mocha.js


    【解决方案1】:

    当我只需要在窗口上模拟某个函数时,我一直在编写类似于您提出的测试:

    it('html test', function () {
        const windowRef = global.window;
        global.window = {document: {querySelector: () => null}};
        const lib = require('lib-that-uses-queryselector');
        assert(true);
        global.window = windowRef;
    });
    

    当我想要一个更完整的窗口对象时,我一直在其他测试中使用mock-browser

    it('html test', function () {
         const windowRef = global.window;
         const MockBrowser = require('mock-browser').mocks.MockBrowser;
         global.window = new MockBrowser().getWindow();
         const lib = require('lib-that-uses-window');
         assert(true);
         global.window = windowRef;
    });
    

    请注意,您可能希望在messing with globals 之后恢复窗口对象(上面的global.window = windowRef;)。

    【讨论】:

    • global.window 为我工作,强烈推荐它,因为您不需要任何额外的库。
    • 我在这里使用了这个想法,但我更喜欢 const window = global.window;全局.window = {...}; ... global.window = 窗口;以防万一在全局范围内添加了一个愚蠢的窗口对象。
    • 真的!编辑以反映这一点。
    • @SimonBengtsson, global.window = window 不会恢复寡妇对象,因为使用window = global.window 创建的窗口常量是通过引用复制的。相反,您可以使用以下命令克隆测试顶部的窗口:preservedWindow = Object.assign({}, window),然后在完成测试时重新分配:global.window = preservedWindow(请注意,由于 Object.assign 仅进行浅拷贝,因此仍然可能存在问题,但在大多数情况下应该足够好例)
    • 嗯,用原来的window对象代替copy不是更好吗?
    【解决方案2】:

    有几个选项可供您使用:

    选项 1:使用JSDOM

    通过在代码中添加 DOM,您可以在 node.js 中对大部分客户端代码进行单元测试

    选项 2:在客户端使用 MOCHA

    Mocha 确实在客户端内部运行,您可以使用单独的客户端单元测试。这往往是我的首选方法,因为我可以针对特定的浏览器而不是特定的 JS 植入进行测试。

    选项 3:使用PhantomJS

    PhantomJS 允许您在测试环境中控制无头浏览器。

    选项 4:Headless Chrome

    现在 Headless Chrome 已经出局,PhantomJS 的维护者已经退休了。

    【讨论】:

    • 我猜JSDOM版本是最快的。它看起来像我需要的!
    • 你为什么要划掉 PhantomJS? 2.0不解决问题吗?
    • @LeeGee “重要提示:PhantomJS 开发暂停,直至另行通知(更多详细信息)。” -- 当有其他可用选项时,我不能推荐不再维护的包。
    • 您能否提供有关选项 2 的更多详细信息? @JeremyJStarcher
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-11
    • 2017-03-27
    • 2019-09-09
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 2021-02-14
    相关资源
    最近更新 更多