1.

スタブ(Stub)とは|テストでの役割とドライバ・モックとの違い

編集
この記事の要点
  • スタブ(Stub)とは、テストなどの場面で、まだ実装されていない呼び出し先や、本物を使いにくい部品の代わりに用意する「仮の部品」のことです。
  • 呼び出されると、あらかじめ決めておいた固定的な値や応答を返すだけの、最小限の実装を持つのが一般的です。
  • スタブは「呼ばれる側」の代用で、上位モジュールから呼び出される下位モジュールの代わりになります。逆に「呼ぶ側」の代用はドライバと呼ばれ、役割が反対です。
  • モック(Mock)は値を返すだけでなく「正しく呼び出されたか」という呼び出しの検証まで行う点でスタブと区別されることが多いとされます。
  • スタブ・ドライバ・モックなどはまとめてテストダブルと総称されます。

スタブとは

スタブ(Stub)とは、テストなどの場面で、まだ実装されていない呼び出し先や、本物をそのまま使うのが難しい部品の代わりに用意する「仮の部品」を指す用語です。本来そこにあるべき機能の形(インターフェース)だけを持ち、中身は呼び出されると決まった値を返す程度の最小限の実装にとどめるのが一般的とされています。

「stub」は英語で「切り株」「(切符などの)半券」といった意味を持つ語です。木を切ったあとに残る根元の部分のように、本来の機能の根元・足場だけを残しておき、必要になったら本物に差し替える、というイメージでとらえると分かりやすいでしょう。

たとえば、あるプログラムが「ユーザー情報を取得する関数」を呼び出すとします。その関数の本体がまだ完成していなくても、「呼ばれたら常に同じダミーのユーザー情報を返す」だけの仮の関数を用意しておけば、呼び出す側のプログラムは動作確認を進められます。この仮の関数がスタブにあたります。

スタブを使う主な場面

スタブは、おもにテストや並行開発の現場で次のような場面に用いられます。

下位モジュールが未完成のときのテスト

大きなソフトウェアは、複数のモジュール(部品)が互いに呼び出し合って成り立っています。上位のモジュールから下位のモジュールを呼び出す構造のとき、下位がまだ完成していないと、上位の動作確認が進められません。

このようなとき、下位モジュールの代わりにスタブを置けば、上位モジュールが「下位を呼び出す」という流れだけを先に検証できます。上位から開発・テストを進めていくトップダウンテストでは、未完成の下位部品をスタブで補う考え方がよく用いられるとされています。

外部API・データベースなどの代わり

外部のWeb APIや、ネットワーク越しのサービス、データベースなどに依存する処理は、テストのたびに本物へアクセスすると問題が起こりやすい領域です。たとえば次のような事情があります。

  • 外部サービスが常に利用できるとは限らず、応答が遅かったり停止していたりすると、テストが不安定になる。
  • 実行のたびに課金が発生したり、本番データを書き換えてしまったりする恐れがある。
  • 「特定のエラーが起きたとき」の挙動など、本物では再現させにくい状況を確認したい。

こうした場合、外部APIやデータベースの代わりにスタブを用意し、「呼ばれたら決まった応答を返す」ようにしておくと、外部の状態に左右されずに自分側のロジックを安定して確認できます。

スタブとドライバの違い

スタブと混同されやすい用語にドライバ(Driver)があります。どちらもテスト用の代用部品ですが、「どちら側の代わりをするか」が反対です。

  • スタブ:テスト対象から呼び出される側(下位)の代用。テスト対象に値を返す役割。
  • ドライバ:テスト対象を呼び出す側(上位)の代用。テスト対象を動かすために呼び出す役割。
観点スタブドライバ
代わりになる位置呼ばれる側(下位モジュール)呼ぶ側(上位モジュール)
テスト対象との関係テスト対象に呼び出されるテスト対象を呼び出す
主な役割決められた値・応答を返すテスト対象に引数を渡して実行する
よく使う場面下位が未完成のトップダウンテスト上位が未完成のボトムアップテスト

上位モジュールから先に作っていく場合は、足りない下位の代わりにスタブが必要になります。逆に下位モジュールから先に作っていくボトムアップテストでは、まだ存在しない上位の代わりとしてドライバが必要になる、という整理が一般的です。

スタブとモック(Mock)の違い

スタブとよく比較されるのがモック(Mock)です。両者はどちらもテスト用の代用部品ですが、目的の置き方に違いがあるとされています。

  • スタブ:あらかじめ決めておいた値や応答を返すことが主な目的。「テスト対象に必要な入力(状態)を与える」ための部品という位置づけです。
  • モック:値を返すことに加えて、「どのように呼び出されたか」を記録・検証することが主な目的。「期待した手続きが行われたか(振る舞い)」を確かめるための部品という位置づけです。

たとえば「メール送信機能が正しく1回だけ呼ばれたか」を確かめたい場合、実際にメールを送らずに呼び出された回数や引数を検証するのはモックの典型的な使い方です。一方スタブは、呼び出され方そのものは問わず、「呼ばれたらこの値を返す」という入力の提供に徹します。

観点スタブモック
主な目的決まった値・応答を返す呼び出され方の検証
確認したいことテスト対象が正しい結果を出すか(状態)正しい手順で呼び出したか(振る舞い)
呼び出し回数・引数基本的に問わない期待どおりかを検証する
イメージ入力を与える代用品やり取りを監視する代用品

ただし、スタブとモックの線引きは文献やツールによって表現が異なる場合があります。実務では両者を厳密に区別せず、まとめて「モック」と呼ぶ場面も見られます。用語が指す範囲はチームや文脈によって揺れがある点に留意するとよいでしょう。

テストダブルという分類

スタブやドライバ、モックのように「本物の代わりにテストで使う部品」を総称してテストダブル(Test Double)と呼びます。「ダブル」は映画の代役(スタントダブル)に由来する言い回しとされています。

テストダブルは、一般に次のような種類に分類して説明されることが多いです(分類の名称や粒度は資料によって異なります)。

  • ダミー(Dummy):引数の数合わせなどのために渡されるだけで、実際には使われない部品。
  • スタブ(Stub):呼ばれると決められた値・応答を返す部品。
  • モック(Mock):呼び出され方を検証する部品。
  • フェイク(Fake):簡略化しつつも実際に動作する代用実装(例:メモリ上だけで動く簡易データベースなど)。
  • スパイ(Spy):本物の処理を行いつつ、呼び出し情報を記録する部品。

スタブはこのうちの一種類であり、「テストダブル」という大きな枠組みの中に位置づけられる、と理解しておくと混乱しにくくなります。

具体例:固定値を返すスタブ

イメージをつかむために、簡単な例を見てみます。ここでは「ユーザーIDを渡すとユーザー名を返す関数」がまだ完成していない、という状況を考えます。本物の代わりに、次のような常に同じ値を返すスタブを用意します(擬似的なコードです)。

// 本物の getUserName はまだ未完成
// テスト用に「呼ばれたら必ず "テスト太郎" を返す」スタブを用意する

function getUserNameStub(userId) {
  // 引数の内容にかかわらず、決め打ちの値を返すだけ
  return "テスト太郎";
}

// このスタブを使って、呼び出し側のロジックを確認できる
const name = getUserNameStub(123);
if (name === "テスト太郎") {
  // 呼び出し側が「名前を受け取って表示する」流れを検証できる
}

このスタブは、引数 userId が何であっても "テスト太郎" を返すだけの最小限の実装です。本物のデータベース検索やAPI呼び出しを行わないため、外部の状態に左右されず、呼び出し側のロジック(受け取った名前をどう扱うか)を安定して確認できます。

なお、条件分岐のテストでは「引数に応じて返す値を切り替えるスタブ」を用意することもあります。たとえば userId が存在しない値のときだけ空の結果を返す、といった具合です。コード中で不等号を扱う場合は、if (count < 0) のように表記されます。

スタブを使うときの落とし穴

注意点内容
本物との挙動の乖離スタブは決め打ちの値を返すため、本物の部品が後から仕様変更されると、スタブとの間にずれが生じます。スタブを使ったテストが通っていても、本物どうしをつないだ段階で不具合が出ることがあるため、結合段階での確認も欠かせません。
スタブのままリリース仮実装のスタブを本物に差し替え忘れたまま出荷してしまうと、常に固定値を返すなどの不具合につながります。スタブはあくまで一時的な代用であることを意識し、差し替え漏れを防ぐ仕組み(目印や検索しやすい命名など)を設けておくと安心です。
モックとの混同「値を返すだけのスタブ」と「呼び出しを検証するモック」を取り違えると、本来確認したいことを確認できていないテストになりがちです。状態を確かめたいのか、呼び出し手順を確かめたいのかを意識して使い分けるとよいとされています。
作り込みすぎスタブに複雑なロジックを入れすぎると、スタブ自体が新たなバグの温床になり、メンテナンスも負担になります。スタブは「必要な応答を返す最小限」にとどめるのが基本です。

よくある質問(FAQ)

Q1. スタブとモックは結局どう使い分ければよいですか?

大まかには、「テスト対象が正しい結果(状態)を出すか」を確かめたいときはスタブ「正しい手順で呼び出したか(振る舞い)」を確かめたいときはモックと整理すると分かりやすいでしょう。たとえば「取得したデータをもとに正しく計算できるか」を見たいならスタブで入力を与え、「保存処理が確かに1回呼ばれたか」を見たいならモックで呼び出しを検証する、といった使い分けです。ただし両者の境界は文脈によって揺れるため、チーム内での呼び方を合わせておくことも大切とされています。

Q2. スタブとドライバはどちらを使えばよいのでしょうか?

テストの進め方によって変わります。上位モジュールから先に作って下位を後回しにするトップダウンなら、足りない下位の代わりにスタブが必要です。下位から先に作って上位を後回しにするボトムアップなら、まだない上位の代わりにドライバが必要になります。「呼ばれる側が足りなければスタブ、呼ぶ側が足りなければドライバ」と覚えると整理しやすいでしょう。

Q3. スタブを使えば本物のテストは不要になりますか?

いいえ、不要にはなりません。スタブはあくまで仮の応答を返す代用品であり、本物の部品が持つ細かな挙動までは再現しないのが一般的です。スタブを使ったテストは「呼び出し側のロジック確認」には有効ですが、本物どうしをつないだときに初めて見つかる問題もあります。スタブによる単体での確認と、本物を組み合わせた結合段階の確認は、役割が異なるものとして両方を行うことが望ましいとされています。

編集
Post Share
子ページ

子ページはありません

同階層のページ

同階層のページはありません

最近更新/作成されたページ