Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
学ぶ Unittestにおける高度なモック | Unittestフレームワークの習得
Python構造化プログラミング

bookUnittestにおける高度なモック

メニューを表示するにはスワイプしてください

前章では、テストにおけるMockの重要性について説明しました。ここでは、さまざまな機能を詳しく見て、不明瞭な点を明確にします。

MagicMockの紹介

MagicMockは、マジックメソッドをサポートする非常に柔軟なMockの実装です。前章で見たように、テスト内で複雑なオブジェクトの挙動を模倣するために利用できます。

from unittest.mock import MagicMock
import unittest

class BankAccount:
    def __init__(self, id):
        self.id = id
        self.balance = self.get_account_balance(id)

    def get_account_balance(self, id):
        # Simulates a database call
        pass

class TestBankAccount(unittest.TestCase):
    def test_balance_retrieval(self):
        account = BankAccount(1)
        account.get_account_balance = MagicMock(return_value=1000)
        self.assertEqual(account.balance, 1000)

この例では、MagicMockを使って通常はデータベースからデータを取得するget_account_balanceメソッドを模擬しています。

mock.patchの利用

@mock.patchは、コード内のオブジェクトの実装を一時的に置き換えるために使用します。

例えば、ユーザー認証情報をデータベースと照合する関数があるとします。mock.patchを使うことで、実際のデータベースへのアクセスを回避できます。

from unittest.mock import patch
import unittest

def authenticate(username, password):
    # Assume this function checks credentials against a database
    pass

class TestAuthentication(unittest.TestCase):
    @patch('module_containing.authenticate')
    def test_login(self, mock_auth):
        mock_auth.return_value = True
        response = authenticate('user', 'pass')
        self.assertTrue(response)

コンテキストマネージャによるモック

場合によっては、デコレータの代わりにpatch()をコンテキストマネージャとして利用する方が適しています。特に以下の場合です:

  • テストの一部だけでオブジェクトをモックしたい場合
  • または、 デコレータやパラメータの多用によってテストの可読性が低下している場合
from unittest.mock import patch
import unittest

class BankAccount:
    def __init__(self, id):
        self.id = id
        self.balance = self.get_account_balance(id)

    def get_account_balance(self, id):
        # Simulates a database call
        return 0

class TestBankAccount(unittest.TestCase):
    def test_balance_retrieval(self):
        with patch.object(BankAccount, 'get_account_balance', return_value=1000) as mock_get:
            account = BankAccount(1)
            self.assertEqual(account.balance, 1000)
            mock_get.assert_called_once_with(1)

Pytest Monkey Patch

Pytestmonkeypatchフィクスチャは、テスト中にクラス、モジュール、または環境を一時的に変更できます。

import os
import pytest

def test_api_url(monkeypatch):
    # Set the API_URL environment variable to a test URL
    monkeypatch.setenv('API_URL', 'https://testapi.com')

    # Now check that the environment variable was set correctly
    assert os.environ['API_URL'] == 'https://testapi.com'

monkeypatchフィクスチャを使うことで、テスト範囲外に副作用を及ぼすことなく、テスト中に安全に環境を変更・管理できます。

1. 次のコードスニペットのうち、get_balance メソッドを正しくモックして 500 を返すものはどれですか?

2. 次のテストは何を検証していますか?

question mark

次のコードスニペットのうち、get_balance メソッドを正しくモックして 500 を返すものはどれですか?

正しい答えを選んでください

question mark

次のテストは何を検証していますか?

正しい答えを選んでください

すべて明確でしたか?

どのように改善できますか?

フィードバックありがとうございます!

セクション 5.  5

AIに質問する

expand

AIに質問する

ChatGPT

何でも質問するか、提案された質問の1つを試してチャットを始めてください

セクション 5.  5
some-alt