unittest.mock によるモック
依存関係をモック化して、テスト対象の単位を分離します。
「unittest.mock によるモック」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。
モックを使う理由
モックは、実際の依存関係(データベース、API、ファイルシステム)を制御可能なテスト用の偽物に置き換えます。これにより、テストを高速かつ決定的に、分離された状態で実行できます。
from unittest.mock import Mock
api = Mock()
api.get_user.return_value = {"id": 1, "name": "Alice"}
result = api.get_user(1)
print(result) # {'id': 1, 'name': 'Alice'}MockとMagicMock
Mockは基底クラスです。MagicMockはマジックメソッド(ダンダーメソッド)を自動設定するため、イテレーターやコンテキストマネージャーなどとして使用できます。
from unittest.mock import MagicMock
m = MagicMock()
m.__len__.return_value = 5
print(len(m)) # 5
m.__iter__.return_value = iter([1, 2, 3])
for x in m:
print(x)デコレーターとしてのpatch
@patchを使うと、テストの実行中だけモジュール内のオブジェクトをモックに置き換えられます。
from unittest.mock import patch
def get_data():
import requests
return requests.get("https://api.example.com").json()
@patch("requests.get")
def test_get_data(mock_get):
mock_get.return_value.json.return_value = {"key": "value"}
result = get_data()
assert result == {"key": "value"}コンテキストマネージャーとしてのpatch
より局所的なモックには、patch()をコンテキストマネージャーとして使います。
from unittest.mock import patch
def test_open():
with patch("builtins.open", create=True) as mock_open:
mock_open.return_value.__enter__.return_value.read.return_value = "data"
with open("file.txt") as f:
assert f.read() == "data"patch.object
patch.object(target, attribute)は、既存のオブジェクトまたはクラスにある特定の属性をパッチします。
from unittest.mock import patch
import mymodule
def test_method():
with patch.object(mymodule.MyClass, "fetch", return_value=42):
obj = mymodule.MyClass()
assert obj.fetch() == 42呼び出しの検証
モックはすべての呼び出しを記録します。assert_called_once_with、assert_called_with、call_countを使って動作を検証できます。
from unittest.mock import Mock
send = Mock()
send("hello", to="alice")
send.assert_called_once_with("hello", to="alice")
print(send.call_count) # 1return_valueとside_effect
return_valueを設定すると、モックが返す値を制御できます。side_effectを使うと、例外を発生させたり、呼び出しごとに異なる値を返したりできます。
from unittest.mock import Mock
m = Mock(side_effect=[1, 2, ValueError("done")])
print(m()) # 1
print(m()) # 2
m() # raises ValueErrorspec:型安全なモック
spec=MyClassを渡すと、実際のクラスに存在する属性だけにモックの使用を制限できます。
from unittest.mock import Mock
class Calc:
def add(self, a, b): return a + b
m = Mock(spec=Calc)
m.add(1, 2) # OK
# m.subtract(1, 2) # AttributeError: Mock does not have 'subtract'patch.dict
patch.dictを使うと、辞書(環境変数やモジュールレベルの設定など)を一時的に変更できます。
from unittest.mock import patch
import os
def test_env():
with patch.dict(os.environ, {"DEBUG": "true"}):
assert os.environ["DEBUG"] == "true"
assert "DEBUG" not in os.environpytest-mockによるpytestでのモック
pytest-mockは、unittest.mockをラップし、各テスト後に自動で後処理を行うmockerフィクスチャーを提供します。
# pip install pytest-mock
def test_service(mocker):
mocker.patch("mymodule.requests.get", return_value=mocker.Mock(
json=lambda: {"status": "ok"}
))
from mymodule import call_api
assert call_api()["status"] == "ok"コルーチン用のAsyncMock
AsyncMockを使うと、awaitされる非同期関数をモックできます。
from unittest.mock import AsyncMock, patch
import asyncio
async def fetch():
import httpx
async with httpx.AsyncClient() as c:
r = await c.get("https://example.com")
return r.json()
def test_fetch():
with patch("httpx.AsyncClient.get", new_callable=AsyncMock) as m:
m.return_value.json.return_value = {"ok": True}
result = asyncio.run(fetch())
assert result["ok"] is Trueクイックチェック
呼び出されたときにMockが返す値を制御するには、どの属性を設定しますか。
まとめ
unittest.mockは、Mock、MagicMock、patch、AsyncMockを提供します。return_valueとside_effectで動作を制御し、アサーションメソッドでモックがどのように呼び出されたかを検証します。
よくある質問
「unittest.mock によるモック」レッスンは無料ですか?
はい。「unittest.mock によるモック」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。
「unittest.mock によるモック」で何を学びますか?
依存関係をモック化して、テスト対象の単位を分離します。 ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Python Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「unittest.mock によるモック」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPython Academyレッスンでコードを書いて実行できますか?
はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 初めての pytest テストを作成する
- フィクスチャとセットアップ/ティアダウン
- パラメーター化とテストカバレッジ
- unittest.mock によるモック