Burlarse de los globales en Broma


¿Hay alguna forma en broma de burlarse de objetos globales, como navigator, o Image*? Prácticamente he renunciado a esto, y lo dejé a una serie de métodos de utilidad simulables. Por ejemplo:

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

Probar esta pequeña función es simple, pero crufty y no determinista en absoluto. Puedo conseguir el 75% del camino allí, pero esto es lo más lejos que puedo ir:

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

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

Por otro lado, si estoy de acuerdo con esta indirección, ahora puedo acceder a navigator a través de estas utilidades:

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

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

        /* More implementation */            
    }
}

...y deterministamente prueba como esta...

// 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();
});

De todos los frameworks de prueba que he usado, Jest se siente como la solución más completa, pero cada vez que escribo código incómodo solo para hacerlo comprobable, siento que mis herramientas de prueba me están decepcionando.

¿Es esta la única solución o necesito agregar Rewire?

* No sonrías. Image es fantástico para hacer ping a un recurso de red remoto.

Author: Andrew, 2016-11-06

2 answers

Como cada prueba ejecuta su propio entorno, puede burlarse de los globales simplemente sobrescribiéndolos. Se puede acceder a todos los VAR globales mediante el espacio de nombres global.

global.navigator = {
  onLine: true
}

La sobrescritura solo tiene efectos en su prueba actual y no afectará a otros. Esta también es una buena manera de manejar Math.random o Date.now

Tenga en cuenta que a través de algunos cambios en jsdom podría ser posible que tenga que burlarse de los globales como este:

Object.defineProperty(globalObject, key, { value, writable: true });
 48
Author: Andreas Köberle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-10 16:58:21

Jest puede haber cambiado desde que se escribió la respuesta aceptada, pero Jest no parece restablecer su global después de la prueba. Por favor, consulte los casos de prueba adjuntos.

Https://repl.it/repls/DecentPlushDeals

Por lo que sé, la única manera de evitar esto es con un afterEach() o afterAll() para limpiar sus asignaciones a global.

 2
Author: smeltedcode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-19 19:46:03