Mockowanie za pomocą unittest.mock
Proszę izolować testowane jednostki przez mockowanie zależności.
Mockowanie za pomocą unittest.mock to bezpłatna lekcja Python Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Python Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Python Academy zawiera 4 lekcji w sumie.
Po co używać mocków
Mocki zastępują rzeczywiste zależności (bazy danych, interfejsy API, system plików) kontrolowanymi atrapami, dzięki czemu testy działają szybko, deterministycznie i w izolacji.
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 i MagicMock
Mock to klasa bazowa. MagicMock automatycznie konfiguruje metody magiczne/dunder, dzięki czemu może być używany jako iterator, menedżer kontekstu itd.
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 jako dekorator
Użyj @patch, aby na czas testu zastąpić obiekt w module mockiem.
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 jako menedżer kontekstu
Użyj patch() jako menedżera kontekstu, aby ograniczyć zakres mockowania.
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) zastępuje konkretny atrybut istniejącego obiektu lub klasy.
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() == 42Sprawdzanie wywołań
Mocki rejestrują każde wywołanie. Użyj assert_called_once_with, assert_called_with i call_count, aby zweryfikować zachowanie.
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 i side_effect
Ustaw return_value, aby kontrolować wartość zwracaną przez mock. Użyj side_effect, aby zgłaszać wyjątki lub zwracać różne wartości w kolejnych wywołaniach.
from unittest.mock import Mock
m = Mock(side_effect=[1, 2, ValueError("done")])
print(m()) # 1
print(m()) # 2
m() # raises ValueErrorspec: mocki bezpieczne typowo
Przekaż spec=MyClass, aby ograniczyć mock do atrybutów istniejących w rzeczywistej klasie.
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
Użyj patch.dict, aby tymczasowo zmodyfikować słownik (np. zmienne środowiskowe lub konfiguracje na poziomie modułu).
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.environMocki w pytest za pomocą pytest-mock
pytest-mock udostępnia fixture mocker, który opakowuje unittest.mock i automatycznie sprząta po każdym teście.
# 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 dla korutyn
Użyj AsyncMock, aby mockować funkcje asynchroniczne, na które czeka się za pomocą 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 TrueSzybkie sprawdzenie
Jaki atrybut należy ustawić w obiekcie Mock, aby kontrolować wartość zwracaną podczas jego wywołania?
Podsumowanie
unittest.mock udostępnia Mock, MagicMock, patch i AsyncMock. Używaj return_value i side_effect do kontrolowania zachowania, a metod asercji do weryfikowania sposobu wywołania mocków.
Często zadawane pytania
Czy lekcja „Mockowanie za pomocą unittest.mock” jest bezpłatna?
Tak — pełny tekst „Mockowanie za pomocą unittest.mock” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Python Academy, przejdź na CoddyKit PRO. Kurs Python Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Mockowanie za pomocą unittest.mock”?
Proszę izolować testowane jednostki przez mockowanie zależności. Ćwiczysz Python Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Python Academy?
Nie wymagamy żadnego doświadczenia. Python Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Mockowanie za pomocą unittest.mock”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Python Academy?
Tak. Każda lekcja Python Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Pisanie pierwszych testów pytest
- Fixtures oraz konfiguracja i sprzątanie
- Parametryzacja i pokrycie testami
- Mockowanie za pomocą unittest.mock