📝

【初学者向け】MockとMagicMockとは?

に公開

 

はじめに

Pythonでテストコードをみると、よく出てくるのが Mock(モック)MagicMock(マジックモック) です。
初学者の方だと、名前は知っていても「結局なに?」「どっちを使えばいいの?」と迷う人は多いと思います。
この記事では、「Mockとは?」「MagicMockとは?」について説明し、その上でそれぞれの使い方について解説します。
 

Mockとは?

Mock(モック)とは、テストで使う“本物の代わりに動くダミー のことです。

  • 本物を呼ぶと遅い/お金がかかる/環境に依存する
  • テストでは「ロジック」だけを確認したい

そんなときに Mockを使えば、好きな戻り値を返すようにできる ので、外部依存を切り離してテストできます。
さらにMockは 「呼び出し回数」「引数」などの履歴を検証できる という機能も持っています。
 

MagicMockとは?

MagicMock(マジックモック)はMockを拡張したもの です。
 
Mockの機能はそのままに、さらに

  • len(obj)
  • for x in obj:
  • obj[0]

といった 特殊メソッド(マジックメソッド) も自動でモック化できます。
 
つまり「リストっぽく」「ファイルっぽく」振る舞わせたいときに使うのがMagicMockです。
 

テストの種類とMockの役割

テストにはいくつか段階があります。

  • 単体テスト … 関数やクラスなど、プログラムの部品単位で正しく動くか
  • 結合テスト … 部品をつなげて正しく動くか

👉 Mock/MagicMockは 主に単体テストで使います。
 

単体テストでのMockの使い方

例:会員ランクに応じて割引メッセージを返す関数。

python

# app.py
def build_message(get_rank, user_id):
    rank = get_rank(user_id)  # ← DBや外部APIを想定
    if rank == "gold":
        return "10%OFF!"
    return "通常価格です"

この get_rank がDBやAPI依存だと単体テストがややこしい。
そこでMockに置き換えます。

python

# test_app.py
import unittest
from unittest.mock import Mock
from app import build_message

class TestBuildMessage(unittest.TestCase):
    def test_gold_member(self):
        fake = Mock(return_value="gold")  # 外部の代わり
        msg = build_message(fake, user_id=123)

        self.assertEqual(msg, "10%OFF!")
        fake.assert_called_once_with(123)  # 呼び出しも検証できる

👉 Mockを使うと 「ロジックだけ」 を確認でき、外部依存を切り離せるのです。

MagicMockが活きる例

例:カートに商品が入っているか確認する関数。

python

#def has_items(cart):
    return len(cart) > 0

ここで普通のMockを渡すと len(cart) はエラーになります。
MagicMockならOK。

python

import unittest
from unittest.mock import MagicMock
from app import has_items

class TestCart(unittest.TestCase):
    def test_cart_with_items(self):
        cart = MagicMock()
        cart.__len__.return_value = 2
        self.assertTrue(has_items(cart))

    def test_cart_empty(self):
        cart = MagicMock()
        cart.__len__.return_value = 0
        self.assertFalse(has_items(cart))

👉 特殊メソッドを含むオブジェクト をモック化したいときはMagicMockを選びます。
 

疑問:全部MagicMockでよくないか

そう思うのですが、一応

  • 動作はする → MagicMockはMockの機能をすべて持つ
  • でも推奨されない

L MagicMockは多機能すぎて、存在しない属性でも動いてしまい間違いに気づきにくい
L Mockの方が「ただのダミー」だと意図が伝わりやすい

👉 ベストプラクティスは

  • 基本はMock
  • 特殊メソッドが必要なときだけMagicMock

が良いとのこと。
 

補足:スタブとの違い

  • Stub(スタブ):決め打ちの値を返すだけの代用品
  • Mock:Stubの機能に加えて「呼び出し履歴の検証」ができる

👉 MockはStubの進化版 と覚えておけばOKです。

スタブの記事はこちら↓

https://zenn.dev/aoao/articles/84e50e62d299f9

まとめ

  • Mock = 本物の代わりに動く + 呼び出し検証ができる
  • MagicMock = Mockの拡張版。len() など特殊メソッドを扱いたいときに使う
  • スタブ = ただの代用品(Mockの基礎)
  • 使い分け = 基本はMock、必要なときだけMagicMock

Discussion