87

navigator、またはImage*などのグローバル オブジェクトを Jest でモックする方法はありますか? 私はこれをほとんどあきらめ、一連のモック可能なユーティリティ メソッドに任せました。例えば:

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

この小さな関数のテストは簡単ですが、扱いにくく、決定論的ではありません。私は 75% まで行くことができますが、これは私ができる限りのことです:

// 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次のユーティリティを介してアクセスできるようになりました。

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

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

        /* More implementation */            
    }
}

...そして、このように決定論的にテストします...

// 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 は最も完全なソリューションのように感じますが、テスト可能にするためだけにぎこちないコードを書くときはいつでも、私のテスト ツールが私を失望させているように感じます。

これが唯一の解決策ですか、それとも Rewire を追加する必要がありますか?

*にやにや笑わないでください。Imageリモート ネットワーク リソースに ping を実行するのに最適です。

4

6 に答える 6

116

すべてのテスト スイートは独自の環境を実行するため、上書きするだけでグローバルをモックできます。globalすべてのグローバル変数は、名前空間からアクセスできます。

global.navigator = {
  onLine: true
}

上書きは現在のテストでのみ効果があり、他のテストには影響しません。これもMath.randomorを処理する良い方法Date.nowです。

jsdomのいくつかの変更により、次のようにグローバルをモックする必要がある可能性があることに注意してください。

Object.defineProperty(globalObject, key, { value, writable: true });
于 2016-11-07T08:02:57.090 に答える