Mock¶
Mock-Objekte fördern Tests, die auf dem Verhalten von Objekten basieren. Die Python-Bibliothek mock ermöglicht euch, Teile des zu testenden Systems durch Scheinobjekte zu ersetzen und Aussagen über deren Verwendung zu treffen.
Installation¶
mock ist seit Python 3.3 in der Python-Standardbibliothek enthalten. Für ältere Versionen von Python könnt ihr sie installieren mit:
$ bin/python -m pip install mock
Beispiel¶
In unserem Beispiel wollen wir prüfen, ob die Arbeitstage von Montag bis Freitag korrekt ermittelt werden.
Zunächst importieren wir
datetime
undMock
:
[1]:
from datetime import datetime
from unittest.mock import Mock
Dann definieren wir zwei Testtage:
[2]:
monday = datetime(year=2021, month=10, day=11)
saturday = datetime(year=2021, month=10, day=16)
Nun definieren wir eine Methode zur Überprüfung der Arbeitstage, wobei die
datetime
-Bibliothek von Python Montage als0
und Sonntage als6
behandelt:
[3]:
def is_workingday():
today = datetime.today()
return (0 <= today.weekday() < 5)
Dann mocken wir
datetime
:
[4]:
datetime = Mock()
Schließlich testen wir unsere beiden Mock-Objekte:
[5]:
datetime.today.return_value = monday
assert is_workingday()
[6]:
datetime.today.return_value = saturday
assert not is_workingday()
[7]:
datetime.today.return_value = monday
assert not is_workingday()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
Cell In[7], line 2
1 datetime.today.return_value = monday
----> 2 assert not is_workingday()
AssertionError:
mock.ANY
¶
Mit mock.ANY könnt ihr prüfen, ob ein Wert überhaupt vorhanden ist, ohne einen genauen Wert prüfen zu müssen:
[8]:
from unittest.mock import ANY
mock = Mock(return_value=None)
mock("foo", bar=object())
mock.assert_called_once_with("foo", bar=ANY)
Hinweis:
In test_report.py des OpenStack Containerdienstes Zun findet ihr weitere praktische Beispiele für ANY
.
patch
-Dekorator¶
Um Mock-Klassen oder Objekte zu erzeugen, kann der patch
-Dekorator verwendet werden. In den folgenden Beispielen wird die Ausgabe von os.listdir
gemockt. Dazu muss die Datei example.txt
nicht im Verzeichnis vorhanden sein:
[9]:
import os
from unittest import mock
[10]:
@mock.patch("os.listdir", mock.MagicMock(return_value="example.txt"))
def test_listdir():
assert "example.txt" == os.listdir()
test_listdir()
Alternativ kann der Rückgabewert auch separat definiert werden:
[11]:
@mock.patch("os.listdir")
def test_listdir(mock_listdir):
mock_listdir.return_value = "example.txt"
assert "example.txt" == os.listdir()
test_listdir()