デバウンス機能の単体テストを作成しようとしています。私はそれについて考えるのに苦労しています。
これはコードです:
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);
};
}
どのように始めるべきですか?
おそらく、デバウンサー関数のロジックを確認する必要があります。
timeout
は常に最後のif()
ステートメントによって設定されますthis
は常にundefined
になります 矢印関数は「囲んでいるレキシカルコンテキストのthis
値」を使用 およびdebouncer()
がスタンドアロン機能として使用するように設計されています。そうは言っても、あなたの本当の質問は、バウンスされた関数のテストに関するもののようです。
モックを使用して関数呼び出しを追跡し、偽のタイマーを使用して時間の経過をシミュレートすることにより、関数のデバウンスをテストできます。
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
});
実際、デバウンスをテストするために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);
});
});
あなたのコードでそうしている場合:
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
私はモカを使用しているので、これが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);
});