Python Mock Raise-Ausnahme
-
Auslösen einer Ausnahme bei Verwendung der Unit-Testing-Bibliothek
unittest
in Python - Manuelles Auslösen einer Ausnahme von einer Funktion
Das Hauptziel dieses Artikels ist es zu demonstrieren, wie man eine Ausnahme auslöst, wenn man die Unit-Testing-Bibliothek unittest
verwendet.
Auslösen einer Ausnahme bei Verwendung der Unit-Testing-Bibliothek unittest
in Python
Um zu überprüfen, ob unser Code stabil ist und die meisten Anwendungsfälle im Rahmen des Projekts berücksichtigt, müssen wir ihn testen, indem wir ihm verschiedene Eingaben geben. Eine der in Python vorhandenen Bibliotheken, unittest
, bietet eine solche Funktionalität, mit der man verschiedene Testfälle schreiben und ausführen kann.
Beim Testen ist es notwendig, mit Fällen umgehen zu können, in denen die Eingabe unerwartet ist. Wir können solche Fälle behandeln, indem wir eine Ausnahme auslösen, die angibt, was mit der gegebenen Eingabe nicht stimmt.
Betrachten Sie den folgenden Code:
class A:
def __init__(self):
pass
def computeData(self):
return 0
class B:
def method_to_test():
obj = A()
try:
print(obj.computeData())
except Exception as e:
print("Exception at method_to_test: " + str(e))
Nehmen wir an, die Funktion, die wir testen möchten, ist method_to_test
. Es initialisiert das Objekt einer anderen Klasse A
und ruft dann eine seiner Methoden namens computeData
in einem try-except
-Block auf, um Ausnahmen abzufangen.
Wenn wir das Verhalten von computeData
testen wollen, wenn eine bestimmte Ausnahme ausgelöst wird, müssen wir dies mit dem Modul unittest
tun.
Ausnahme einmal auslösen
In Anbetracht des oben erwähnten Szenarios kann es auch sein, dass wir mehr Kontrolle darüber haben möchten, wann eine Ausnahme ausgelöst wird.
Es kann viele Gründe geben, warum ein solcher Bedarf entstehen kann. Abhängig von der Implementierung Ihres Codes kann es sehr hilfreich sein, mehr Kontrolle über das Verhalten zu haben.
Ausnahme bestätigen
Beim Schreiben von Testfällen möchten Sie möglicherweise prüfen, ob Ihre Ausnahmen ausgelöst werden oder nicht. Dies ist besonders nützlich, wenn Sie wissen möchten, ob eine Ausnahme ausgelöst wurde oder nicht.
Dies kann Ihnen helfen, in Ihren Testfällen früher zu erkennen, wenn etwas schief geht.
Mock-Module von Drittanbietern
Module von Drittanbietern können je nach unserer Implementierung von fast keinen bis zu vielen reichen. Um zu testen, ob sich ein Modul eines Drittanbieters wie beabsichtigt verhält, müssen wir sein Verhalten auch mit unterschiedlichen Ausgaben testen.
Ein solches Beispiel wäre request
, ein weit verbreitetes Modul bei der Kommunikation über ein Netzwerk oder beim Senden/Empfangen von Daten über HTTP.
Manuelles Auslösen einer Ausnahme von einer Funktion
Um manuell eine Ausnahme von der computeData
-Funktion auszulösen, müssen wir das side_effect
-Attribut verwenden.
Betrachten Sie den folgenden Code:
import unittest
from unittest.mock import patch
from unittest.mock import MagicMock
class A:
def __init__(self) -> None:
pass
def computeData(self):
return 0
class B:
def method_to_test():
obj = A()
try:
print(obj.computeData())
except Exception as e:
print("Exception at method_to_test: " + str(e))
class Test(unittest.TestCase):
@patch.object(A, "computeData", MagicMock(side_effect=Exception("Test")))
def test_method(self):
B.method_to_test()
if __name__ == "__main__":
Test().test_method()
Ausgang:
Exception at method_to_test: Test
In der Lösung wird eine neue Methode test_method
erstellt, um die Methode method_to_test
zu testen. Wichtig ist auch zu beachten, dass die Funktion mit patch.object
verziert wird.
Der Decorator patch
wird im Modul zum Patchen von Modulen und Attributen auf Klassenebene bereitgestellt. Um genauer zu sagen, was gepatcht werden soll, verwenden wir das patch.object
anstelle von patch
, um die Methode direkt zu patchen.
Im Decorator wird der Klassenname A
übergeben. Dies zeigt an, dass das zu patchende Objekt ein Teil von A
ist, wobei der Mitgliedsname computeData
übergeben wird.
Der letzte Parameter ist ein MagicMock
-Objekt, eine Unterklasse von Mock
, wo wir unser erforderliches Verhalten mit computeData
verknüpfen, indem wir das side_effect
-Attribut verwenden, das in unserem Fall eine Ausnahme auslöst.
Der allgemeine Ablauf des Programms ist wie folgt:
- Die
test_method
wird aufgerufen. - Die
computeData
der KlasseA
werden gepatcht. Einside_effect
wird zugewiesen, was in unserem Fall eine Ausnahme darstellt. - Die
method_to_test
der KlasseB
wird aufgerufen. - Der Konstruktor der Klasse
A
wird aufgerufen, wobei die Instanz inobj
gespeichert wird. - Die
computeData
werden aufgerufen. Aufgrund der gepatchten Methode wird eine Ausnahme ausgelöst.
Lösen Sie einmal eine Ausnahme aus
Um die Ausnahme nur einmal auszulösen oder mehr Kontrolle über das Verhalten der Funktion zu haben, unterstützt side_effect
mehr als nur einen Funktionsaufruf.
Aktuell unterstützt side_effect
:
Iterierbar
Aufrufbar
Ausnahme
(Instanz oder Klasse)
Mit Iterable
können wir dafür sorgen, dass die Methode nur einmal eine Ausnahme auslöst.
class Test(unittest.TestCase):
@patch.object(A, "computeData", MagicMock(side_effect=[1, Exception("Test"), 3]))
def test_method(self):
B.method_to_test()
if __name__ == "__main__":
testClass = Test()
testClass.test_method()
testClass.test_method()
testClass.test_method()
Ausgang:
1
Exception at method_to_test: Test
3
Durch das übergebene Iterable
werden Elemente unserer Wahl gepatcht und wir erhalten die Kontrolle darüber, wann Ausnahmen ausgelöst werden. Daher wird die Exception erst beim zweiten Aufruf der Funktion geworfen, andernfalls werden 1
und 3
zurückgegeben.
Ausnahme bestätigen
Um festzustellen, ob eine bestimmte Ausnahme aufgetreten ist oder nicht, können wir unittest.TestCase.assertRaises
verwenden, falls unsere gewünschte Ausnahme nicht ausgelöst wird.
class Test(unittest.TestCase):
@patch.object(A, "computeData", MagicMock(side_effect=Exception("Test")))
def test_method(self):
self.assertRaises(KeyError, A.computeData)
if __name__ == "__main__":
Test().test_method()
Ausgang:
Exception at method_to_test: Test
Traceback (most recent call last):
File "d:\Python Articles\a.py", line 28, in <module>
Test().test_method()
File "C:\Program Files\Python310\lib\unittest\mock.py", line 1369, in patched
return func(*newargs, **newkeywargs)
File "d:\Python Articles\a.py", line 25, in test_method
self.assertRaises(KeyError, A.computeData)
File "C:\Program Files\Python310\lib\unittest\case.py", line 738, in assertRaises
return context.handle('assertRaises', args, kwargs)
File "C:\Program Files\Python310\lib\unittest\case.py", line 201, in handle
callable_obj(*args, **kwargs)
File "C:\Program Files\Python310\lib\unittest\mock.py", line 1104, in __call__
return self._mock_call(*args, **kwargs)
File "C:\Program Files\Python310\lib\unittest\mock.py", line 1108, in _mock_call
return self._execute_mock_call(*args, **kwargs)
File "C:\Program Files\Python310\lib\unittest\mock.py", line 1163, in _execute_mock_call
raise effect
File "d:\Python Articles\a.py", line 17, in method_to_test
Exception: Test
Wir nehmen geringfügige Änderungen an unserer Methode test_method
vor und rufen assertRaises
mit zwei Parametern auf, was zu der obigen Ausgabe führte.
Die beiden Parameter können wie folgt definiert werden:
KeyError
- Jede Ausnahme, die Sie auslösen möchten, wird hier übergeben.A.computeData
- Die Methode, die die Ausnahme auslösen soll.
Mock-Module von Drittanbietern
Um einen post
zu verspotten, müssen Sie wie zuvor den Decorator patch
verwenden. Ein einfaches Beispiel kann wie folgt aussehen:
class Test(unittest.TestCase):
@patch(
"requests.post", MagicMock(side_effect=requests.exceptions.ConnectionError())
)
def test_method(self):
requests.post()
Ausgang:
Traceback (most recent call last):
File "d:\Python Articles\a.py", line 33, in <module>
Test().test_method()
File "C:\Program Files\Python310\lib\unittest\mock.py", line 1369, in patched
return func(*newargs, **newkeywargs)
File "d:\Python Articles\a.py", line 30, in test_method
requests.post()
File "C:\Program Files\Python310\lib\unittest\mock.py", line 1104, in __call__
return self._mock_call(*args, **kwargs)
File "C:\Program Files\Python310\lib\unittest\mock.py", line 1108, in _mock_call
return self._execute_mock_call(*args, **kwargs)
File "C:\Program Files\Python310\lib\unittest\mock.py", line 1163, in _execute_mock_call
raise effect
requests.exceptions.ConnectionError
Die Funktionen von Modulen von Drittanbietern können auch mit dem patch
-Decorator gepatcht werden, was ein besseres Debugging und mehr Kontrolle über das Ausmaß der Zuverlässigkeit des Produkts/Programms ermöglicht.
Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.
LinkedInVerwandter Artikel - Python Exception
- Ausnahme in Python erneut auslösen
- Open-File-Ausnahmebehandlung in Python
- Ausnahme in Python auslösen
- Python except Exception as e
- Python assert Ausnahme