お知らせ

現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。

以下のようなコードを書いたときにmockFnにイベント引数が渡らないが、これをどうにかして取る方法。結論から言うとまともに取れないが、試行錯誤した時のログとして残しておく

const mockFn = jest.fn();
render(<input onChange={mockFn} />);
fireEvent.change(inputElement, { target: { value: 'aaa' } });

確認環境

Env Ver
@swc/core 1.3.66
@swc/jest 0.2.26
@testing-library/jest-dom 5.16.5
@testing-library/react 14.0.0
jest 29.5.0
react 18.2.0

サンプルコード

これは以下のように書くとfireEventの第二引数で指定したtarget.valueの部分だけは一応取れる。

理由としてはfireEventelement.dispatchEventを読んでいると思われるためだ。余り深くは追っていないが、react-testing-libraryの実装上は多分そうなっていると思われる。

import { fireEvent, render } from '@testing-library/react';

it('test', () => {
  const mockFn = jest.fn((ev) => {
    console.log(ev);
  });
  const { container } = render(<input id="hoge" onChange={mockFn} value={'a'} />);
  const element = container.querySelector('input');
  if (element === null) throw new Error();
  element.dispatchEvent = jest.fn();
  fireEvent.change(element, {
    target: {
      value: 'bbb'
    }
  });

  expect(element.dispatchEvent.mock.instances[0].value).toBe('bbb');
});
投稿日:
Node.js

標準入力から読み込みたい時に

確認環境

Env Ver
Node.js 20.11.0

サンプルコード

/dev/stdinが存在するPOSIX系のシステム限定だと思われる。UbuntuとFreeBSDでは動いた。

const { readFileSync } = require('node:fs');

const stdIn = readFileSync('/dev/stdin', 'utf8');
console.log(stdIn);

おまけ

Markdownテキストを標準入力から取得して、生成したHTMLを標準出力に吐くやつ

サーバーサイドでMarkedを使いたかったので。Node.js 20系はC++やclangのバージョンが古くエラーになると思われるので18系にした

前提

  • さくらのレンタルサーバースタンダードプラン
  • zshを利用している

手順

所要時間はさくらのレンタルサーバースタンダードプランで2時間丁度くらい

  1. nodebrewを落としてくる
wget git.io/nodebrew
  1. .zshrcにパスを通す

    1. PATH=${HOME}/.nodebrew/current/bin:${PATH}
  2. コンパイルして使えるようにする

perl nodebrew setup
## バージョン確認
# nodebrew ls-remote
## プロセスが殺されるのを防ぐためにniceで優先度を下げている
## コンパイルには2h程かかる
nice -n 20 nodebrew compile v18.19.0
nodebrew use v18.19.0

試したけどうまくいかなかったやつ

nvm

niceが効かないのでプロセスキルされて終わる

フルスクラッチコンパイル

OpenSSL周りに何か問題があるらしくコンパイルがこける。バージョンが合ってないのかも

# OpenSSL
wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz
tar -zxvf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w
./config --prefix=/home/$USERNAME/openssl --openssldir=/home/$USERNAME/local/openssl
make
make install

# Node.js
wget https://nodejs.org/dist/v18.9.1/node-v18.9.1.tar.gz
tar -zxvf node-v18.9.1.tar.gz
cd node-v18.9.1
./configure --shared-openssl --shared-openssl-includes=/home/$USERNAME/openssl/include/
export LD_LIBRARY_PATH=/home/$USERNAME/openssl/lib
make install DESTDIR=/home/$USERNAME/local PREFIX=

所感

Node.jsなので負荷が心配だったが、Markedでブログ記事をMarkdownからHTMLに落とす程度なら問題なく動いて安心した。

EdgeとChromeは同じだったがNode.jsでは異なる挙動をしていたのでそのメモ

確認環境

Env ver
Microsoft Edge 120.0.2210.9
Google Chrome 120.0.6099.130
Node.js 20.0.0

環境別の確認結果

Edge

DevToolsで確認

const err = new Error('test');
Object.getPrototypeOf(err);

// {name: 'Error', message: '', constructor: ƒ, toString: ƒ}

Google Chrome

DevToolsで確認

const err = new Error('test');
Object.getPrototypeOf(err);

// {name: 'Error', message: '', constructor: ƒ, toString: ƒ}

Node.js

node -iで確認

const err = new Error('test');
Object.getPrototypeOf(err);

// {}

JestからNode.js組み込みのテストランナーに移行する時の方法や注意点をまとめたメモ

確認環境

Env ver
Node.js 20.8.0
Jest 29.7

Node.jsの組み込みテストランナーとは

英語圏ではNode.js built-in test runnerとか呼ばれている存在で、Node.jsの組み込みテストランナーのこと。恐らくDenoのテストランナーに対抗して生まれた気配がする(Node.jsはDenoに機能追加があると真似する傾向があるため

Node.jsの組み込みテストランナーは機能が二分されており、テストランナーアサートに分かれている

Jestみたいにエコシステムが発達しておらず、標準ではdescribeなどはimportする必要がある。TypeScriptをテストする場合は間にレジスター[^1]を嚙ます必要があるが、本項では扱わない

Jest関数との対応リスト

describe, it, beforeAll, afterAll, beforeEach, afterEach辺りは違和感がなかったが、それ以外は軒並み互換性がないので大きく書き換えが必要だと感じた。便利なMatcherは完膚なきまでに全滅している。お陰で覚えることが減ったのは逆に良くなったと感じる

なお、not始まりの機能は実際の動作を確認しておらず、Jestと同じ機能かどうかは確認していないことに留意すること

describe(name, fn), it(name, fn, timeout?), test(name, fn, timeout?)

Node.jsのTest機能では、以下となる

  • describe([name][, options][, fn])
  • it([name][, options][, fn])
  • test([name][, options][, fn])

基本的な差はないがJestにあったtimeout引数はNode.jsではoptionsパラメーターで設定するようになっている模様。今回調べるまで存在自体を知らなかったのもあり、このtimeoutがJestと同じ機能かどうかは確認していない

import { describe, it } from 'node:test';

describe('hoge', () => {
  it('hoge', () => {
    // ここにテストコード
  });

  it.todo('piyo');
});

beforeAll(fn, timeout?), afterAll(fn, timeout?), beforeEach(fn, timeout?), afterEach(fn, timeout?)

Node.jsのTest機能では、以下となる

  • before([fn][, options])
  • after([fn][, options])
  • beforeEach([fn][, options])
  • afterEach([fn][, options])

基本的な差はないがJestにあったtimeout引数はNode.jsではoptionsパラメーターで設定するようになっている模様。今回調べるまで存在自体を知らなかったのもあり、このtimeoutがJestと同じ機能かどうかは確認していない

+import { after, before, beforeEach, afterEach, describe } from 'node:test';
+
 describe('test', () => {
-  beforeAll(() => {
+  before(() => {
     console.log('before');
   });
   beforeEach(() => {
     console.log('beforeEach');
   });
   afterEach(() => {
     console.log('afterEach');
   });
-  afterAll(() => {
+  after(() => {
     console.log('after');
   });
 });

.toBe(value), .not.toBe(value)

Node.jsのTest機能では、以下となる

  • assert.strictEqual(actual, expected[, message])
  • assert.notStrictEqual(actual, expected[, message])
+import { describe, it } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
     const actual = 123;

-    expect(actual).toBe(123);
+    assert.deepStrictEqual(actual, 123);
   });
 });

.toStrictEqual(value), .not.toStrictEqual(value)

Node.jsのTest機能では、以下となる

  • assert.deepStrictEqual(actual, expected[, message])
  • assert.notDeepStrictEqual(actual, expected[, message])
+import { describe, it } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
     const actual = {
       hoge: {
         piyo: {
           id: 1,
           value: 'one'
         }
       },
       fuga: [[123, 456], 'ABC', 'EFG']
     };

-    expect(actual).toStrictEqual({
+    assert.deepStrictEqual(actual, {
       hoge: {
         piyo: {
           id: 1,
           value: 'one'
         }
       },
       fuga: [[123, 456], 'ABC', 'EFG']
     });
   });
 });

.toHaveLength(number), .toBeNull(), .toBeUndefined(), .toBeNaN()

Node.jsのTest機能では、assert.strictEqual()となる

+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
     const arr = [1, 2, 3];
     const undef = undefined;
     const nil = null;
     const nan = NaN;

-    expect(arr).toHaveLength(3);
-    expect(undef).toBeUndefined();
-    expect(nil).toBeNull();
-    expect(nan).toBeNaN();
+    assert.strictEqual(arr.length, 3);
+    assert.strictEqual(undef, undefined);
+    assert.strictEqual(nil, null);
+    assert.strictEqual(nan, NaN);
   });
 });

.toBeTruthy()

Node.jsのTest機能では、以下となる

  • assert.ok(value[, message])

否定版は不明

+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
-    expect(true).toBeTruthy();
-    expect({}).toBeTruthy();
-    expect([]).toBeTruthy();
-    expect(42).toBeTruthy();
-    expect('0').toBeTruthy();
-    expect('false').toBeTruthy();
-    expect(new Date()).toBeTruthy();
-    expect(-42).toBeTruthy();
-    expect(12n).toBeTruthy();
-    expect(3.14).toBeTruthy();
-    expect(Infinity).toBeTruthy();
-    expect(-Infinity).toBeTruthy();
+    assert.ok(true);
+    assert.ok({});
+    assert.ok([]);
+    assert.ok(42);
+    assert.ok('0');
+    assert.ok('false');
+    assert.ok(new Date());
+    assert.ok(-42);
+    assert.ok(12n);
+    assert.ok(3.14);
+    assert.ok(Infinity);
+    assert.ok(-Infinity);
   });
 });

.toBeInstanceOf(Class)

Node.jsのTest機能では、assert.ok()となる

結果がTruthyであればなんでもpassするので注意

+import { describe, it } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
     const actual = new Error('hoge');

-    expect(actual).toBeInstanceOf(Error);
+    assert.ok(actual instanceof Error);
   });
 });

.toThrow, not.toThrow

Node.jsのTest機能では、以下となる

  • assert.throws(fn[, error][, message])
  • assert.doesNotThrow(fn[, error][, message])

Jestより便利になっており、Error型以外も扱えるので後述する

+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
     const err = new Error('test');

-    expect(() => {
+    assert.throws(() => {
       throw err;
-    }).toThrow(err);
+    }, err);
   });
 });
Node.jsではJestと異なりError型以外も扱える

Jestの`.toThrow()はError型以外を扱うことができず、オブジェクトをThrowするようなコードではエラーになる

describe('test', () => {
  it('test', () => {
    const obj = { id: 1, value: 'hoge' };

    // このテストは失敗する。またTypeScriptの型エラーにもなる
    expect(() => {
      throw obj;
    }).toThrow(obj);
    // このテストは失敗する。またTypeScriptの型エラーにもなる
    expect(() => {
      throw obj;
    }).toThrow({ id: 1, value: 'hoge' });
  });
});

しかしNode.jsであればこれはエラーにならない。例えば次のテストコードは成功する

import { describe, it, mock } from 'node:test';
import assert from 'node:assert';

describe('test', () => {
  it('test', () => {
    const obj = { id: 1, value: 'hoge' };

    assert.throws(() => {
      throw obj;
    }, obj);
    assert.throws(
      () => {
        throw obj;
      },
      { id: 1, value: 'hoge' }
    );
  });
});

expect.arrayContaining(array), expect.objectContaining(object), expect.stringContaining(string)

恐らく非対称マッチャーはないので自分でロジックを書いてassert.strictEqual()で判定するしかないと思われる。元々微妙な機能だったのでやむなし

jest.spyOn(object, methodName, accessType?)

Node.jsのTest機能では、node:testからmockをimportして以下を使う

  • mock.method(object, methodName[, implementation][, options])
+import { describe, it, mock } from 'node:test';
+
 describe('test', () => {
   it('test', () => {
-    jest.spyOn(console, 'log');
+    mock.method(console, 'log');
   });
 });
本来の挙動を塞ぎたい場合

例えば以下のようにテストコードを書いた場合、execSync()が実際の挙動で動作してしまい、テストとして機能しない。

import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
import child_process, { execSync } from 'node:child_process';

const mockedExecSync = mock.method(child_process, 'execSync');

describe('execSync', () => {
  it('execSyncが正しい引数で呼ばれること', () => {
    execSync('false');

    assert.strictEqual(mockedExecSync.mock.calls[0].arguments[0], 'false');
  });
});

このような場合、以下のようにmock.method()の第三引数を指定してやると封じることができる。単体テストの観点では基本的に第三引数には空関数を入れておくのが望ましいだろう。

import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
import child_process, { execSync } from 'node:child_process';

- const mockedExecSync = mock.method(child_process, 'execSync');
+ const mockedExecSync = mock.method(child_process, 'execSync', () => {});

describe('execSync', () => {
  it('execSyncが正しい引数で呼ばれること', () => {
    execSync('false');

    assert.strictEqual(mockedExecSync.mock.calls[0].arguments[0], 'false');
  });
});
モックパターン
module.exportsされている関数のモック

import foo from 'foo';形式でmock.method()の第一引数を埋める

import { describe, it, mock } from 'node:test';
import assert from 'node:assert';
import child_process, { execSync } from 'node:child_process';

const mockedExecSync = mock.method(child_process, 'execSync', () => {});

describe('execSync', () => {
  it('execSyncが正しい引数で呼ばれること', () => {
    execSync('false');

    assert.strictEqual(mockedExecSync.mock.calls[0].arguments[0], 'false');
  });
});

上記が正常に動作することはNode.js v20.0.0時点のコードで確認している

Global objectから生えている関数のモック

以下のようにmock.method()の第一引数にGlobal objectを設定すればよい

import { describe, it, mock } from 'node:test';
import assert from 'node:assert';

describe('exit', () => {
  // exitが実際に走って落ちるのでmock.methodの第三引数を指定している
  const mockedExit = mock.method(process, 'exit', () => {});

  it('call exit', () => {
    process.exit(1);

    assert.strictEqual(mockedExit.mock.calls.length, 1);
  });
});
Named exportされている関数のモックは今のところ無理そう

ファイルモックをする手段がないので正攻法では無理そう
https://github.com/nodejs/help/issues/4298

一応力技でやる方法はググれば出てくるが…

ObjectやNamespaceでラップされている関数のモック

実装例(Object)

export const Hoge = {
  validateFoo() {
    // 例外を飛ばす可能性のある何かの処理
  },
  hoge() {
    Hoge.validateFoo();

    return 1;
  },
};

実装例(Namespace)

export namespace Hoge {
  export const validateFoo = () => {
    // 例外を飛ばす可能性のある何かの処理
  };
  export const hoge = () => {
    validateFoo();

    return 1;
  };
}

実装例に対するテストコード

ObjectもNamespaceも同じ書き方でテスト可能

import { describe, it } from 'node:test';
import assert from 'node:assert';
import { Hoge } from './hoge';

describe('hoge', () => {
  it('validateFooが例外をスローした場合、例外がスローされること', (t) => {
    t.mock.method(Hoge, 'validateFoo', () => {
      throw new Error('foo');
    });

    assert.throws(() => {
      Hoge.hoge();
    }, Error('foo'));
  });

  it('全ての関数が正常終了した場合、戻り値を返すこと', () => {
    const actual = Hoge.hoge();

    assert.strictEqual(actual, 1);
  });
});

.toHaveBeenCalled(), .toHaveBeenCalledTimes(number)

Node.jsのTest機能では、assert.strictEqual()でモックから生えてるやつを調べる。returnも同様の手法で実現できる

+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
-    const spiedConsoleLog = jest.spyOn(console, 'log');
+    const mockedConsoleLog = mock.method(console, 'log');

     console.log();

-    expect(spiedConsoleLog).toHaveBeenCalled();
-    expect(spiedConsoleLog).toHaveBeenCalledTimes(1);
+    assert.deepStrictEqual(mockedConsoleLog.mock.calls.length, 1);
   });
 });

.toHaveBeenCalledWith(arg1, arg2, ...)

Node.jsのTest機能では、assert.strictEqual()でモックから生えてるやつを調べる。returnも同様の手法で実現できる。

Jestでは.toEqual()処理されるがNode.jsの組み込みテストランナーの場合、厳密比較ができるので便利

+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
-    const spiedConsoleLog = jest.spyOn(console, 'log');
+    const mockedInfo = mock.method(console, 'log');

     console.log('test');

-    expect(spiedConsoleLog).toHaveBeenCalledWith('test');
+    assert.deepStrictEqual(mockedInfo.mock.calls[0].arguments[0], 'test');
   });
 });

jest.fn(implementation?)

Node.jsのTest機能では、以下となる

  • mock.fn([original[, implementation]][, options])
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
+// 動作確認用の関数
 const testTarget = (cbParam: string, callbackFn: (param: string) => number) => {
   return callbackFn(cbParam);
 };

 describe('test', () => {
   it('test', () => {
-    const mockFn = jest.fn((_: string) => {
+    const mockFn = mock.fn((_: string) => {
       return 5;
     });
     const actual = testTarget('hoge', mockFn);

-    expect(mockFn).toBeCalledWith('hoge');
-    expect(mockFn).toReturnWith(5);
-    expect(actual).toBe(5);
+    assert.deepStrictEqual(mockFn.mock.calls[0].arguments[0], 'hoge');
+    assert.deepStrictEqual(mockFn.mock.calls[0].result, 5);
+    assert.deepStrictEqual(actual, 5);
   });
 });

jest.useFakeTimers(fakeTimersConfig?), jest.runAllTimers()

Node.jsのTest機能では、以下となる

  • mock.timers.enable([timers])
  • mock.timers.runAll()
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
+describe('test', () => {
-  jest.useFakeTimers();
+  mock.timers.enable();

+  it('test', () => {
-    const mockFn = jest.fn();
+    const mockFn = mock.fn();
     setTimeout(() => {
       mockFn();
     }, 9999);

-    expect(mockFn).not.toHaveBeenCalled();
-    jest.runAllTimers();
-    expect(mockFn).toHaveBeenCalledTimes(1);
+    assert.deepStrictEqual(mockFn.mock.calls.length, 0);
+    mock.timers.runAll();
+    assert.deepStrictEqual(mockFn.mock.calls.length, 1);
   });
 });

jest.useRealTimers()

Node.jsのTest機能では、以下となる

  • mock.timers.reset()
+import { mock } from 'node:test';

-jest.useRealTimers();
+mock.timers.reset();

mockFn.mockClear()

Node.jsのTest機能では、以下となる

  • ctx.resetCalls()
+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
-    const mockFn = jest.fn((param: string) => `<${param}>`);
+    const mockFn = mock.fn((param: string) => `<${param}>`);

     mockFn('hoge');
-    expect(mockFn).toHaveBeenCalledTimes(1);
-    expect(mockFn).toReturnWith('<hoge>');
+    assert.deepStrictEqual(mockFn.mock.calls.length, 1);
+    assert.deepStrictEqual(mockFn.mock.calls[0].result, '<hoge>');

-    mockFn.mockClear();
+    mockFn.mock.resetCalls();

-    expect(mockFn).toHaveBeenCalledTimes(0);
+    assert.deepStrictEqual(mockFn.mock.calls.length, 0);
     mockFn('piyo');
-    expect(mockFn).toHaveBeenCalledTimes(1);
-    expect(mockFn).toReturnWith('<piyo>');
+    assert.deepStrictEqual(mockFn.mock.calls.length, 1);
+    assert.deepStrictEqual(mockFn.mock.calls[0].result, '<piyo>');
   });
 });

mockFn.mockReset()

Node.jsのTest機能では、以下となる

  • mockFn.mock.restore()

振る舞いが微妙に違うため後述する

+import { describe, it, mock } from 'node:test';
+import assert from 'node:assert';
+
 describe('test', () => {
   it('test', () => {
-    const spiedConsoleLog = jest
-      .spyOn(console, 'log')
-      .mockImplementation((param: any) => {
-        return `<${param}>`;
-      });
+    const mockedConsoleLog = mock.method(console, 'log', (param: any) => {
+      return `<${param}>`;
+    });

     console.log('hoge');
-    expect(spiedConsoleLog).toHaveBeenCalledTimes(1);
-    expect(spiedConsoleLog).toReturnWith('<hoge>');
+    assert.deepStrictEqual(mockedConsoleLog.mock.calls.length, 1);
+    assert.deepStrictEqual(mockedConsoleLog.mock.calls[0].result, '<hoge>');

-    spiedConsoleLog.mockReset();
+    mockedConsoleLog.mock.restore();
   });
 });

JestとNode.jsでの振る舞いの差異

但しJestとNode.jsのTest機能では微妙に差異がある

例えばJestでは以下の実装が正しくPASSするが

describe('test', () => {
  it('test', () => {
    const mockFn = jest
      .spyOn(console, 'log')
      .mockImplementation((param: any) => {
        return `<${param}>`;
      });

    console.log('hoge');
    expect(mockFn).toHaveBeenCalledTimes(1);
    expect(mockFn).toReturnWith('<hoge>');

    mockFn.mockReset();

    expect(mockFn).toHaveBeenCalledTimes(0);
    console.log('piyo');
    expect(mockFn).toHaveBeenCalledTimes(1);
    expect(mockFn).not.toHaveBeenCalledWith();
    expect(mockFn).toReturnWith(undefined);
  });
});

Node.jsで以下の実装を書いても同じように機能しない

import { describe, it, mock } from 'node:test';
import assert from 'node:assert';

describe('test', () => {
  it('test', () => {
    const mockFn = mock.method(console, 'log', (param: any) => {
      return `<${param}>`;
    });

    console.log('hoge');
    assert.deepStrictEqual(mockFn.mock.calls.length, 1);
    assert.deepStrictEqual(mockFn.mock.calls[0].result, '<hoge>');

    mockFn.mock.resetCalls();
    mockFn.mock.restore();

    assert.deepStrictEqual(mockFn.mock.calls.length, 0);
    console.log('piyo');
    // 以降のテストはいずれも落ちる
    assert.deepStrictEqual(mockFn.mock.calls.length, 1);
    assert.deepStrictEqual(mockFn.mock.calls[0].result, '<piyo>');
  });
});

但しモック実装を削除したうえで再度呼び出すという行為には意味がないので、特に問題にはならないと思われる

モック機能についての備考

it([name][, options][, fn])の第三引数のコールバックの第一引数にはTestContextが入っており、これを使ってモックすることもできる

これを使う場合、スコープアウトでモックが復元されるため、例えば以下のような関数をテストするときに便利である。

実装

export namespace Hoge {
  export const validateFoo = () => {
    // 例外を飛ばす可能性のある何かの処理
  };

  export const validateBar = () => {
    // 例外を飛ばす可能性のある何かの処理
  };

  export const validateBaz = () => {
    // 例外を飛ばす可能性のある何かの処理
  };

  export const hoge = () => {
    validateFoo();
    validateBar();
    validateBaz();

    return 1;
  };
}

テストコード

import { describe, it } from 'node:test';
import assert from 'node:assert';
import { Hoge } from './hoge';

describe('hoge', () => {
  it('validateFooが例外をスローした場合、例外がスローされること', (t) => {
    t.mock.method(Hoge, 'validateFoo', () => {
      throw new Error('foo');
    });

    assert.throws(() => {
      Hoge.hoge();
    }, Error('foo'));
  });

  it('validateBarが例外をスローした場合、例外がスローされること', (t) => {
    t.mock.method(Hoge, 'validateBar', () => {
      throw new Error('bar');
    });

    assert.throws(() => {
      Hoge.hoge();
    }, Error('bar'));
  });

  it('validateBazが例外をスローした場合、例外がスローされること', (t) => {
    t.mock.method(Hoge, 'validateBaz', () => {
      throw new Error('baz');
    });

    assert.throws(() => {
      Hoge.hoge();
    }, Error('baz'));
  });

  it('全ての関数が正常終了した場合、戻り値を返すこと', () => {
    const actual = Hoge.hoge();

    assert.strictEqual(actual, 1);
  });
});