LoginSignup
7
7

More than 5 years have passed since last update.

Promise.thenをasync/awaitを使って同期させてテストする方法(jest)

Last updated at Posted at 2017-04-28

問題

Promise.thenは非同期なので.then内で起こる事をテストしようとしても、時系列的にthenの内容が評価される前にテストが走ってしまい結果としてテストが失敗する。

例えばこういうPromiseを内部で返す関数があり、この.then内で何かしらの評価をしたい場合

promise.async.js
export default class PromiseTest{
  fetchData(callback){
    this.fetch().then(({status}) => {
      if(status == "ok"){
        callback()
      }
    })
  }

  fetch(){
    return new Promise((resolve, reject) => {
      resolve({
        status: "ok"
      })
    })
  }
}

コールバックをmockして、呼ばれるかどうか確認したいがテストが先に走り、その後に.thenが呼ばれるためテストが失敗する

promise.async.js
import PromiseTest from "./promise.async"

describe('PromiseTest', () => {
  describe('async/awaitなし', () => {
    it('先にテストが走るので、失敗する', () => {
      const mockCallback = jest.fn()
      const target = new PromiseTest()

      target.fetchData(mockCallback)
      expect(mockCallback).toHaveBeenCalled()
    });
  });
});

解決方法

async/awaitを使う
これによりtarget.fetchData(mockCallback)が終わるまで待ってくれるので、続くテストがその後に実行され、正しく評価する事が可能になる。

promise.sync.js
import PromiseTest from "./promise.async"
import "babel-polyfill"

describe('PromiseTest', () => {
  describe('async/awaitアリ', () => {
    it('成功する', async () => {
      const mockCallback = jest.fn()
      const target = new PromiseTest()

      await target.fetchData(mockCallback)
      expect(mockCallback).toHaveBeenCalled()
    });
  });
});

注意

import "babel-polyfill"
をしないと
ReferenceError: regeneratorRuntime is not defined
が起きる
参照

diff --git a/promise.async.spec.js b/promise.sync.spec.js
index e856584..0661e6b 100644
--- a/promise.async.spec.js
+++ b/promise.sync.spec.js
@@ -1,12 +1,13 @@
 import PromiseTest from "./promise.async"
+import "babel-polyfill"

 describe('PromiseTest', () => {
-  describe('async/awaitなし', () => {
-    it('先にテストが走るので、失敗する', () => {
+  describe('async/awaitアリ', () => {
+    it('成功する', async () => {
       const mockCallback = jest.fn()
       const target = new PromiseTest()

-      target.fetchData(mockCallback)
+      await target.fetchData(mockCallback)
       expect(mockCallback).toHaveBeenCalled()
     });
   });
7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7