Estoy tratando de escribir una prueba unitaria para la función antirrebote. Me está costando mucho pensarlo.

Este es el código:

function debouncer(func, wait, immediate) {
  let timeout;

  return (...args) => {
    clearTimeout(timeout);

    timeout = setTimeout(() => {
      timeout = null;
      if (!immediate) func.apply(this, args);
    }, wait);

    if (immediate && !timeout) func.apply(this, args);
  };
}

¿Cómo debo comenzar?

7
RecipeCreator 7 sep. 2018 a las 17:18

3 respuestas

La mejor respuesta

Probablemente desee verificar la lógica en su función antirrebote:

Habiendo dicho eso, parece que su verdadera pregunta es sobre probar funciones sin rebote.

Prueba de funciones eliminadas

Puede probar que una función se elimina mediante el uso de un simulacro para rastrear llamadas a funciones y temporizadores falsos para simular el paso del tiempo.

Aquí hay un ejemplo simple usando una Jest Función simulada y Sinon temporizadores falsos de una función eliminada utilizando debounce() de Lodash:

const _ = require('lodash');
import * as sinon from 'sinon';

let clock;

beforeEach(() => {
  clock = sinon.useFakeTimers();
});

afterEach(() => {
  clock.restore();
});

test('debounce', () => {
  const func = jest.fn();
  const debouncedFunc = _.debounce(func, 1000);

  // Call it immediately
  debouncedFunc();
  expect(func).toHaveBeenCalledTimes(0); // func not called

  // Call it several times with 500ms between each call
  for(let i = 0; i < 10; i++) {
    clock.tick(500);
    debouncedFunc();
  }
  expect(func).toHaveBeenCalledTimes(0); // func not called

  // wait 1000ms
  clock.tick(1000);
  expect(func).toHaveBeenCalledTimes(1);  // func called
});
11
Brian Adams 7 sep. 2018 a las 17:33

En realidad, no necesita usar Sinon para probar los rebotes. Jest puede burlarse de todos los temporizadores en código JS.

Consulte el siguiente código (es TypeScript, pero puede traducirlo fácilmente a JS):

import * as _ from 'lodash';

// tell jest to mock all timeout functions
jest.useFakeTimers();

describe('debounce', () => {

    let func: jest.Mock;
    let debouncedFunc: Function;

    beforeEach(() => {
        func = jest.fn();
        debouncedFunc = _.debounce(func, 1000);
    });

    test('execute just once', () => {
        for (let i = 0; i < 100; i++) {
            debouncedFunc();
        }

        // fast-forward time
        jest.runAllTimers();

        expect(func).toBeCalledTimes(1);
    });
});

Más información: https://jestjs.io/docs/en/timer-mocks.html

6
tswistak 7 dic. 2018 a las 07:15

Si en su código lo está haciendo:

import debounce from 'lodash/debounce';

myFunc = debounce(myFunc, 300);

Y desea probar la función myFunc o una función que la llame, entonces en su prueba puede burlarse de la implementación de debounce usando jest para que solo devuelva su función:

import debounce from 'lodash/debounce';

// Tell jest to mock this import
jest.mock('lodash/debounce');

it('my test', () => {
    // ...
    debounce.mockImplementation(fn => fn); // Assign the import a new implementation, in this case it's execute the function given to you
    // ...
});

Fuente: https://gist.github.com/apieceofbart/d28690d52c46848c39d904ce8968bb27

5
Mis94 8 ene. 2019 a las 10:38