MagicMock を使ってテストコードを作ったので、メモをここに残します。
MagicMock とは
MagicMock は Python の標準ライブラリ unittest.mock に含まれており、テスト対象の関数・メソッド・クラスの動作を模倣(mock)するオブジェクトです。
利用場面
- 外部APIやDBへのアクセスを実際に行いたくない
- 副作用(ファイルI/OやHTTP通信など)を避けたい
- 関数呼び出し回数・引数・戻り値を検証したい
使い方
API 呼び出しをモック
以下のように、api_client が外部 API を呼ぶ想定とします。
def fetch_data(api_client, user_id): """APIクライアントからユーザーデータを取得する関数""" response = api_client.get_user(user_id) return response.get("name", "unknown")
テストでは実際のAPIは呼ばず、MagicMock で代替します。
テストコード
from unittest.mock import MagicMock from sample import fetch_data def test_fetch_data_success(): # --- モックを作成 --- mock_api = MagicMock() mock_api.get_user.return_value = {"name": "Alice"} # --- テスト実行 --- result = fetch_data(mock_api, user_id=123) # --- 検証 --- assert result == "Alice" # get_user が正しい引数で1回呼ばれたことを確認 mock_api.get_user.assert_called_once_with(123)
備考
| `MagicMock()` | モックオブジェクトを生成 |
| `.return_value` | メソッド呼び出し時に返す値を指定 |
| `.assert_called_once_with()` | 呼び出し回数や引数を検証 |
| `.side_effect` | 呼び出し時に例外発生や異なる戻り値をシミュレートできる |
外部 API が例外を返す場合のテスト
def fetch_data(api_client, user_id): try: response = api_client.get_user(user_id) return response["name"] except Exception: return "error"
テストコード
side_effect を使うことで、例外発生や複数の返り値を順番に返すなどの挙動も再現できます。
from unittest.mock import MagicMock from sample import fetch_data def test_fetch_data_error(): mock_api = MagicMock() mock_api.get_user.side_effect = Exception("API Error") result = fetch_data(mock_api, user_id=999) assert result == "error" mock_api.get_user.assert_called_once()
MagicMock の主なメリット
| 外部依存を排除 | DBやAPIを実際に呼ばずにテスト可能 |
| 呼び出し履歴の検証 | 引数・回数・順序などの検証が容易 |
| 高速テスト | 実際のI/Oをしないので高速 |
| 柔軟なカスタマイズ | `return_value` / `side_effect` で任意の動作を再現 |
| unittestと自然に統合 | pytest や unittest と簡単に組み合わせ可能 |