在 Jest 中模拟全局变量 [英] Mocking globals in Jest

查看:146
本文介绍了在 Jest 中模拟全局变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Jest 有没有办法模拟全局对象,例如 navigatorImage*?我几乎放弃了这一点,把它留给了一系列可模拟的实用方法.例如:

Is there any way in Jest to mock global objects, such as navigator, or Image*? I've pretty much given up on this, and left it up to a series of mockable utility methods. For example:

// Utils.js
export isOnline() {
    return navigator.onLine;
}

测试这个小函数很简单,但很粗糙,而且根本不是确定性的.我可以完成 75% 的路程,但这是我所能做到的:

Testing this tiny function is simple, but crufty and not deterministic at all. I can get 75% of the way there, but this is about as far as I can go:

// Utils.test.js
it('knows if it is online', () => {
    const { isOnline } = require('path/to/Utils');

    expect(() => isOnline()).not.toThrow();
    expect(typeof isOnline()).toBe('boolean');
});

另一方面,如果我对这个间接访问没问题,我现在可以通过这些实用程序访问 navigator:

On the other hand, if I am okay with this indirection, I can now access navigator via these utilities:

// Foo.js
import { isOnline } from './Utils';

export default class Foo {
    doSomethingOnline() {
        if (!isOnline()) throw new Error('Not online');

        /* More implementation */            
    }
}

...并像这样确定性地测试...

...and deterministically test like this...

// Foo.test.js
it('throws when offline', () => {
    const Utils = require('../services/Utils');
    Utils.isOnline = jest.fn(() => isOnline);

    const Foo = require('../path/to/Foo').default;
    let foo = new Foo();

    // User is offline -- should fail
    let isOnline = false;
    expect(() => foo.doSomethingOnline()).toThrow();

    // User is online -- should be okay
    isOnline = true;
    expect(() => foo.doSomethingOnline()).not.toThrow();
});

在我使用过的所有测试框架中,Jest 感觉是最完整的解决方案,但是每当我编写笨拙的代码只是为了使其可测试时,我觉得我的测试工具让我失望.

Out of all the testing frameworks I've used, Jest feels like the most complete solution, but any time I write awkward code just to make it testable, I feel like my testing tools are letting me down.

这是唯一的解决方案还是我需要添加重新布线?

Is this the only solution or do I need to add Rewire?

*别傻笑.Image 非常适合 ping 远程网络资源.

*Don't smirk. Image is fantastic for pinging a remote network resource.

推荐答案

由于每个测试套件都运行自己的环境,您可以通过覆盖全局变量来模拟它们.global 命名空间可以访问所有全局变量:

As every test suite run its own environment, you can mock globals by just overwriting them. All global variables can be accessed by the global namespace:

global.navigator = {
  onLine: true
}

覆盖仅对您当前的测试有影响,不会影响其他测试.这也是处理 Math.randomDate.now 的好方法.

The overwrite has only effects in your current test and will not effect others. This also a good way to handle Math.random or Date.now.

请注意,通过 jsdom 中的一些更改,您可能必须像这样模拟全局变量:

Note, that through some changes in jsdom it could be possible that you have to mock globals like this:

Object.defineProperty(globalObject, key, { value, writable: true });

这篇关于在 Jest 中模拟全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆