0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

レガシーなcallbackとprototypeをテストと一緒に書き直す

Last updated at Posted at 2023-05-05

こんばんは。@Esperna です。

背景

前回レガシーなcallbackをasync/awaitで書き直すという記事を書きました。
その際、protoptypeやテストコードについても書きたかったのですが、長くなり過ぎると思ったので別記事にすることにしました。いつもながら車輪の再発明ですが自身の理解を深めるために書いてます。

prototypeでクラスを実現するメソッドの例

asyncTaskOld.js
function AsyncTask() {
    console.log(`made at Showa`);
}

AsyncTask.prototype.doAsync = function (callback) {
    const TIMEOUT = 10;
    const SUCCESS = 1;
    setTimeout(() => {
        callback(SUCCESS);
    }, TIMEOUT);
};

module.exports = new AsyncTask();

classを使ってprototypeを書き直す

下記の通りです。

asyncTask.js
class AsyncTask {
    constructor() {
        console.log(`made at Heisei`);
    }
    doAsync(callback) {
        const TIMEOUT = 10;
        const SUCCESS = 1;
        setTimeout(() => {
            callback(SUCCESS);
        }, TIMEOUT);
    }
}

module.exports = new AsyncTask();

個人的な所感ですが、callback版よりもC++やJavaで見慣れたこちらの方がしっくり来ます。

(async/await使いたいので)Promiseで書き直してみる

asyncTaskNew.js
class AsyncTask {
    constructor() {
        console.log(`made at Reiwa`);
    }
    doAsync() {
        return new Promise((resolve) => {
            const TIMEOUT = 10;
            const SUCCESS = 1;
            setTimeout(() => {
                resolve(SUCCESS);
            }, TIMEOUT);
        });
    }
}

module.exports = new AsyncTask();

今回は上述のasyncTaskOld.jsとasyncTaskNew.jsに対してテストコードを書いてみます。

callbackを引数に取る関数に対するテストコード

asyncTaskOld.test.js
const asyncTask = require("./asyncTaskOld");

describe("asyncTask old class test", () => {
    const SUCCESS = 1;
    test("doAsync shall call callback with SUCCESS", (done) => {
        asyncTask.doAsync((result) => {
            expect(result).toBe(SUCCESS);
            done();
        });
    });
});

Promiseを返すコードに対するテストコード

asyncTaskNew.test.js
const asyncTask = require("./asyncTaskNew");

describe("asyncTask new class test", () => {
    const SUCCESS = 1;
    test("doAsync shall return SUCCESS", async () => {
        const result = await asyncTask.doAsync();
        expect(result).toBe(SUCCESS);
    });
});
  • テストコードを書くという観点でcallback版とPromise版を比べると
    • callback版は引数をマッチャでチェックすることになりネストが深くなります
    • Promise版は戻り値をマッチャでチェックすることになりネストが浅いです
    • callback版はcallbackの処理をチェックしたい場合はcallback関数内でdoneの呼び出しを書いてあげる必要があります

所感

  • テストコードも書きやすくなるのでcallbackではなくPromiseでasync/awaitで書きたいです
  • prototypeかclassかはテストコードには影響なさそうですが、C++やJavaを見慣れているのでprototypeは古い仕様だしできれば使いたくないです
0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?