Google Apps Script でのJestテストコードの書き方


前提

開発環境の構築や設定は、以前に投稿した記事を参考にして構築されているものとします。
Google Apps Script の開発環境構築方法

DocumentAppを利用したサンプルコード

example.ts
// Google Apps Script Services
function createDocument(): string {
  const doc = DocumentApp.create("Hello, world!");
  doc
    .getBody()
    .appendParagraph("This document was created by Google Apps Script.");
  return doc.getId();
}

export { createDocument };

jest.config.jsの設定

jest.config.jsを下記のように変更します

jest.config.js
module.exports = {
  preset: "ts-jest",
  testEnvironment: "node",
  globals: {
    Logger: {},
    DocumentApp: {} // <- 追加
  }
};

テストコード(パターン1)

クラスを定義せずに直接mock化する方法

example.test.ts
import { createDocument } from "../src/example";

describe("example.ts test", () => {
  test("createDocument", () => {
    DocumentApp.create = jest.fn().mockImplementation(name => {
      return {
        getBody: jest.fn().mockImplementation(() => {
          return {
            appendParagraph: jest.fn().mockImplementation(text => {})
          };
        }),
        getId: jest.fn().mockReturnValue("1234567890")
      };
    });
    const expected = createDocument();
    expect(expected).toBe("1234567890");
  });
});

テストコード(パターン2)

mockクラスを定義してmock化する方法
※ファイルへの追記処理をローカルファイルへ追記するエミュレート処理も追加

example.test.ts
import { createDocument } from "../src/example";
import fs = require("fs");

class BodyMock {
  _doc: DocumentMock;
  constructor(doc: DocumentMock) {
    this._doc = doc;
  }
  appendParagraph(text: string): void {
    fs.appendFile(this._doc._name, text, err => {
      if (err) {
        throw err;
      }
    });
  }
}
class DocumentMock {
  _name: string;
  constructor(name: string) {
    this._name = name;
  }
  getBody(): BodyMock {
    return new BodyMock(this);
  }
  getId(): string {
    return "1234567890";
  }
}

describe("example.ts test", () => {
  test("createDocument", () => {
    DocumentApp.create = jest.fn().mockImplementation(name => {
      return new DocumentMock(name);
    });
    const expected = createDocument();
    expect(expected).toBe("1234567890");
  });
});