javasciptで非同期関数を処理する同期関数のテストをしたい


はじめに

テストツールはjestです。

テストしたいコード

export let text = "hoge";
const asyncFunc = async () => {
  await new Promise((resolve) => {
    console.log(text);
    // hoge
    resolve();
  });
  text = "fuga";
  console.log(text);
  // fuga
};

const testFunc = () => {
  asyncFunc();
  console.log(text);
  // hoge
};
export default testFunc;

testFuncの中で非同期関数のasyncFuncが実行されています。

testFuncが実行されると、非同期でtextの値がhogeからfugaに変わることをテストしたい。

テストコード

失敗例


test("testFunc", async () => {
  testFunc();
  expect(text).toBe("fuga");
});

このテストだと失敗します。
text="fuga"を実行しているasyncFuncが非同期だからですね。

成功例


test("testFunc", async () => {
  testFunc();
  expect(text).not.toBe("fuga");
  return new Promise((resolve) => setImmediate(resolve)).then(() => {
    expect(text).toBe("fuga");
  });
});

これでテストが成功します。

Promiseを返すと、jestはPromiseが解決されるまで待機します。
つまり、setImmediateが終わった後にexpect(text).toBe("fuga")が実行されているということになります。

なぜ、setImmediateなのか

jestはNode.jsで動作しています。
Node.jsのイベントループでは、setImmediateが最後に実行されます。

Node.jsのイベントループについてはこちらを参照
https://blog.hiroppy.me/entry/nodejs-event-loop