web-dev-qa-db-ja.com

デバウンス機能のJestユニットテスト

デバウンス機能の単体テストを作成しようとしています。私はそれについて考えるのに苦労しています。

これはコードです:

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

どのように始めるべきですか?

6
RecipeCreator

おそらく、デバウンサー関数のロジックを確認する必要があります。

そうは言っても、あなたの本当の質問は、バウンスされた関数のテストに関するもののようです。

デバウンス機能のテスト

モックを使用して関数呼び出しを追跡し、偽のタイマーを使用して時間の経過をシミュレートすることにより、関数のデバウンスをテストできます。

Jestモック関数 および Sinon偽のタイマー を使用して、 debounce() from 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
});
10
Brian Adams

実際、デバウンスをテストするためにSinonを使用する必要はありません。 JestはすべてのタイマーをJSコードでモックできます。

次のコードを確認してください(TypeScriptですが、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);
    });
});

詳細: https://jestjs.io/docs/en/timer-mocks.html

4
tswistak

あなたのコードでそうしている場合:

import debounce from 'lodash/debounce';

myFunc = debounce(myFunc, 300);

関数myFuncまたはそれを呼び出す関数をテストしたい場合、テストでdebounceを使用してjestの実装をモックして、関数を返すだけにすることができます。

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

ソース: https://Gist.github.com/apieceofbart/d28690d52c46848c39d904ce8968bb27

3
Mis94

私はモカを使用しているので、これがjestでどのように機能するかはわかりませんが、簡単な解決策を探している人のために:

it('debounce.spec', done => {
    // Arrange
    const log = sinon.spy();
    const search = debounce(log, 100);

    // Act
    search();

    // Assert
    setTimeout(() => {
      expect(log.called).to.be.true;
      done();
    }, 100);
  });
0
marrion luaka