Jest|非同期コードのテスト


📌 Calbackモード


🔹 コールバック関数はtest関数に渡されませんでした。


正しくテストされていません.

通過コード


通過(1ミリ秒)して終了するには、3秒(3000ミリ秒)以上かかります.

  • 3秒後に名前が付けられた関数を作成します(fn.js)
    /* 
    getName 함수는 콜백 함수를 받아서 3초 후에 name을 
    콜백의 첫 번째 인수로 넘겨줌. */
    
    const fn = {
      add: (num1, num2) => num1 + num2,
      getName: (callback) => { // 👈
        const name = "Mike";
        setTimeout(() => {
          callback(name);
        }, 3000);
      },
    };
    
    module.exports = fn;

  • 使用するコードの記述(fn.test.js)
    /*
    getName함수 호출하고 콜백 함수 전달. 
    콜백은 name을 받아서 테스트 진행. */
    
    const fn = require("./fn");
    
    test("3초 후에 받아온 이름은 Mike", () => {
      function callback(name) {
        expect(name).toBe("Mike");
      }
      fn.getName(callback);
    });

  • テストnpm test

  • 検査結果
  • 失敗したコード


    テスト、すぐ合格

  • 失敗コードに変更(fn.test.js)
    const fn = require("./fn");
    
    test("3초 후에 받아온 이름은 Mike", () => {
      function callback(name) {
        expect(name).toBe("Tom"); // 👈 Tom으로 수정
      }
      fn.getName(callback);
    });

  • テスト(npm test)後、検証結果
  • 失敗の原因


  • 最もよく使われる非同期モードは、このようにコールバックを使用する方法かもしれません.

  • しかし、Jestは最後まで運行していた時点でそのまま終了した.
    →したがって、所定のコールバック関数は実行できません.
  • fn.test.js
    const fn = require("./fn");
    
    test("3초 후에 받아온 이름은 Mike", () => {
      function callback(name) {
        expect(name).toBe("Tom");
      }
      fn.getName(callback); // 👈 기다리지 않고 그냥 여기서 그냥 끝내는 것.
    });

  • 解決策
    test関数にコールバック関数を渡す(ex.done)
  • 🔹 コールバック関数をtest関数に渡す


    すべてのテストは正常です.
    コールバック関数が呼び出されるまで、Jestはテストの完了を待っていた.

    失敗したコード


  • コールバック関数の転送(done)(fn.test.js)
    const fn = require("./fn");
    
    test("3초 후에 받아온 이름은 Mike", (done) => { // 👈
      function callback(name) {
        expect(name).toBe("Tom");
        done(); // 👈 callback이 실행되고 여기에 done 호출
      }
      fn.getName(callback);
    });

  • テスト(npm test)

  • 失敗(3秒以上)

  • 理由を教えて
    トムを期待していたがマイクが出てきた

  • 通過コード

  • fn.test.jsテストのtoBeをMikeに再変換

  • 検証テスト結果(npm test)
    3秒くらいで通過
  • コールバック関数が呼び出されていない場合


    テストに失敗しました
  • fn.test.js
    const fn = require("./fn");
    
    test("3초 후에 받아온 이름은 Mike", (done) => {
      function callback(name) {
        expect(name).toBe("Mike");
        // done(); // 👈
      }
      fn.getName(callback);
    });
    
    /*
    - 결과:
    한참 걸리다가 실패.
    살펴 보면 Timeout임. 5초 동안 timeout이 있고 그동안 응답이 없으면 실패로 간주. */
  • 97 APIのエラー

    try catchドアで包む
  • サンプルコード
  • try catch文の使用(fn.test.js)
    const fn = require("./fn");
    
    test("3초 후에 받아온 이름은 Mike", (done) => {
      function callback(name) {
        try {  // 👈
          expect(name).toBe("Mike");
          done();
        } catch (error) {  // 👈
          done();
        }
      }
      fn.getName(callback);
    });

  • 関数でエラーが発生しました(fn.js)
    const fn = {
      add: (num1, num2) => num1 + num2,
      getName: (callback) => {
        const name = "Mike";
        setTimeout(() => {
          throw new Error("서버 에러.."); // 👈
        }, 3000);
      },
    };
    
    module.exports = fn;

  • テスト(npm test)後、検証結果
    エラー
  • 📌 Promise


    🔹 使用法(Calbackと比較)

  • より明確で簡潔
  • を超えるコールバック関数は必要ありません&return
  • が必要です

  • コールバック関数をスキップする必要はありませんPromiseからreturnJestからresolveまでです.

  • 関数作成(fn.js)
    受容年齢の関数を作成&3秒後resolve
    const fn = {
    
      (...생략)
    
      getAge: () => {
        const age = 30;
        return new Promise((res, rej)=>{
          setTimeout(()=>{
            res(age)
          }, 3000)
        })
      }
    };
    
    module.exports = fn;

  • テストコードreturnなし(fn.test.js)
    問題がある
    const fn = require("./fn");
    
    test("3초 후에 받아온 나이는 30", () => {
      fn.getAge().then((age) => { // 👈 return 無
        expect(age).toBe(30);
      });
    });

  • テスト結果
    国境を越える.しかし、結果はすぐに出てきた.→おかしい.
  • .toBeの数字(.toBe(31))を変更しても

  • テストコードの追加トラブルシューティングreturn(fn.test.js)
    const fn = require("./fn");
    
    test("3초 후에 받아온 나이는 30", () => {
      return fn.getAge().then((age) => { // 👈
        expect(age).toBe(31);
      });
    });

  • テスト結果

  • 3秒&31が必要なので失敗→動作が正しい
    (returnがなければ、先ほどのようにそのまま終了)

  • 修正.toBe(30);の場合
    3秒&通過→動作正常です.
  • 🔹 マッチングの使用


    簡単に書きたいなら

    ソリューションの例

  • fn.test.js
    const fn = require("./fn");
    
    test("3초 후에 받아온 나이는 30", () => {
      return expect(fn.getAge()).resolves.toBe(30); // 👈
    });
    
    // 테스트 결과: 통과
  • サンプルの拒否


  • 「通じない」なら
  • fn.js
    const fn = {
      (...생략)
      getAge: () => {
        const age = 30;
        return new Promise((res, rej) => {
          setTimeout(() => {
            rej("error"); // 👈 이 부분을 바꿔주면 됨
          }, 3000);
        });
      },
    };
    
    module.exports = fn;
  • fn.test.js
    const fn = require("./fn");
    
    test("3초 후에 받아온 나이는 30", () => {
      return expect(fn.getAge()).rejects.toBe(30); // 👈 rejects로 수정
    });
    
    // 테스트 결과: 실패 -> 제대로 동작

  • パス(Pass)の場合
    エラーを確認するためにtoMatch('error')に変更
  • fn.test.js
    const fn = require("./fn");
    
    test("3초 후에 에러가 납니다.", () => { // 👈 설명 수정
      return expect(fn.getAge()).rejects.toMatch("error"); // 👈
    });
    
    // 테스트 결과: 통과함. (3초 후, 에러 발생) -> 제대로 동작
  • 📌 async, await


    🔹 使用方法

    asyncawaitと同様に使用される.

    成功時


  • 関数(fn.js)
    const fn = {
      (...생략)
      getAge: () => {
        const age = 30;
        return new Promise((res, rej) => {
          setTimeout(() => {
            res(age); // 👈
          }, 3000);
        });
      },
    };
    
    module.exports = fn;

  • テストコード(fn.test.js)
    const fn = require("./fn");
    
    test("3초 후 나이 30", async () => {
      const age = await fn.getAge();
      expect(age).toBe(30);
    });
    
    // 테스트 결과:  통과 -> 제대로 동작
  • 失敗した場合

  • fn.test.jsの数字を置換します.( .toBe(31); )

  • テスト後の検査結果
    3秒-失敗

  • 成功事例への再変更
    30に変更(.toBe(30);)

  • テスト後の検査結果
    成功
  • 🔹 マッチングの使用

    returnではなくawait
  • fn.test.js
    const fn = require("./fn");
    
    test("3초 후 나이 30", async () => { // 👈 async
      await expect(fn.getAge()).resolves.toBe(30); // 👈 await
    });
    
    // 테스트 결과: 통과 -> 제대로 동작
  • リファレンス
  • コード鞍馬教程Jest