Wie teste ich den folgenden Code mit Mocks (unter Verwendung von Mocks, dem Patch-Dekorator und Sentinels, die vom Mock-Framework von Michael Foord bereitgestellt werden ):
def testme(filepath):
with open(filepath, 'r') as f:
return f.read()
python
mocking
with-statement
Daryl Spitzer
quelle
quelle
Antworten:
Die Vorgehensweise hat sich in Mock 0.7.0 geändert, das schließlich das Verspotten der Python-Protokollmethoden (Magic-Methoden) unterstützt, insbesondere mit MagicMock:
http://www.voidspace.org.uk/python/mock/magicmock.html
Ein Beispiel für das Verspotten als Kontextmanager (auf der Beispielseite in der Verspottungsdokumentation):
quelle
__enter__
und__exit__
verspottet werden. Ist der letztere Ansatz veraltet oder immer noch nützlich?file
weg!mock_open
ist Teil desmock
Frameworks und sehr einfach zu bedienen.patch
Als Kontext verwendet gibt das Objekt zurück, das zum Ersetzen des gepatchten Objekts verwendet wird: Sie können es verwenden, um Ihren Test zu vereinfachen.Python 3.x.
Verwenden Sie
builtins
anstelle von__builtin__
.Python 2.7
mock
ist nicht Teil vonunittest
und Sie sollten patchen__builtin__
Dekorateur Fall
Wenn Sie
patch
als Dekorateurmock_open()
das Ergebnis vonnew
patch
'verwenden, kann das Argument des ' etwas seltsam sein.In diesem Fall ist es besser, das
new_callable
patch
Argument von ' zu verwenden und zu beachten, dass alle zusätzlichen Argumente,patch
die nicht verwendet werden, annew_callable
die in derpatch
Dokumentation beschriebene Funktion übergeben werden .Zum Beispiel ist die dekorierte Version für Python 3.x :
Denken Sie daran, dass in diesem Fall
patch
das Scheinobjekt als Argument Ihrer Testfunktion hinzugefügt wird.quelle
with patch("builtins.open", mock_open(read_data="data")) as mock_file:
ob die Syntax in die Dekorationssyntax konvertiert werden kann. Ich habe es versucht, bin mir aber nicht sicher, worauf ich@patch("builtins.open", ...)
als zweites Argument eingehen muss.return_value
vonmock_open
in ein anderes Scheinobjekt kanalisieren und das zweite Scheinobjekt behauptenreturn_value
), aber es funktionierte durch Hinzufügen vonmock_open
alsnew_callable
.six
Modul an, um ein konsistentesmock
Modul zu erhalten. Aber ich weiß nicht, ob es auchbuiltins
in einem gemeinsamen Modul abgebildet ist.Mit den neuesten Versionen von mock können Sie den wirklich nützlichen mock_open- Helfer verwenden:
quelle
.write
Anrufe gibt?handle.write.assert_any_call()
. Sie können auchhandle.write.call_args_list
jeden Anruf erhalten, wenn die Reihenfolge wichtig ist.m.return_value.write.assert_called_once_with('some stuff')
ist besser imo. Vermeidet das Registrieren eines Anrufs.Mock.call_args_list
ist sicherer als das Aufrufen einer derMock.assert_xxx
Methoden. Wenn Sie eine der letzteren als Attribute von Mock falsch buchstabieren, werden sie immer stillschweigend weitergegeben.So verwenden Sie mock_open für eine einfache Datei
read()
(das ursprüngliche mock_open-Snippet, das bereits auf dieser Seite angegeben ist, ist eher zum Schreiben gedacht ):Beachten Sie, dass dies gemäß den Dokumenten für mock_open speziell für ist
read()
und daher nicht mit gängigen Mustern wiefor line in f
z. B. funktioniert .Verwendet Python 2.6.6 / mock 1.0.1
quelle
for line in opened_file:
Codetyp zum Laufen bringen. Ich habe versucht, mit iterierbarem StringIO zu experimentieren, das dies implementiert__iter__
und stattdessen verwendetmy_text
, aber kein Glück.read()
und wird in Ihremfor line in opened_file
Fall nicht funktionieren . Ich habe den Beitrag bearbeitet, um zu verdeutlichenfor line in f:
Unterstützung von @EvgeniiPuchkaryov kann erreicht werden, indem stattdessen der Rückgabewertopen()
als StringIO-Objekt verspottet wird .with open("any_string") as f: print f.read()
Die beste Antwort ist nützlich, aber ich habe sie etwas erweitert.
Wenn Sie den Wert Ihres Dateiobjekts (das
f
Inas f
) basierend auf den an Folgendes übergebenen Argumenten festlegen möchtenopen()
, haben Sie folgende Möglichkeiten:Grundsätzlich
open()
wird ein Objekt zurückgegeben und dieses Objektwith
aufgerufen__enter__()
.Um richtig zu verspotten, müssen wir verspotten
open()
, um ein Scheinobjekt zurückzugeben. Dieses Scheinobjekt sollte dann den__enter__()
Aufruf verspotten (MagicMock
wird dies für uns tun), um das Scheindaten- / Dateiobjekt zurückzugeben, das wir (dahermm.__enter__.return_value
) wollen. Wenn wir dies mit 2 Mocks wie oben beschrieben tun, können wir die übergebenen Argumente erfassenopen()
und an unseredo_something_with_data
Methode übergeben.Ich habe eine ganze Mock-Datei als String übergeben
open()
und meinedo_something_with_data
sah folgendermaßen aus:Dadurch wird die Zeichenfolge in eine Liste umgewandelt, sodass Sie wie bei einer normalen Datei Folgendes tun können:
quelle
__enter__
? Es sieht definitiv eher nach einem Hack als nach einem empfohlenen Weg aus.Ich bin vielleicht etwas spät dran, aber das hat bei mir funktioniert, als ich
open
ein anderes Modul aufgerufen habe, ohne eine neue Datei erstellen zu müssen.test.py
MyObj.py
Durch Patchen der
open
Funktion innerhalb des__builtin__
Moduls auf mymock_open()
kann ich das Schreiben in eine Datei verspotten, ohne eine zu erstellen.Hinweis: Wenn Sie ein Modul verwenden, das Cython verwendet, oder Ihr Programm in irgendeiner Weise von Cython abhängt, müssen Sie das Cython-
__builtin__
Modul importieren , indem Sie esimport __builtin__
oben in Ihre Datei aufnehmen. Sie werden nicht in der Lage sein, das Universelle zu verspotten,__builtin__
wenn Sie Cython verwenden.quelle
import __builtin__
mein Testmodul erweitert wurde. Dieser Artikel half zu klären, warum diese Technik so gut funktioniert wie sie: ichimonji10.name/blog/6So patchen Sie die integrierte open () - Funktion mit unittest:
Dies funktionierte für einen Patch zum Lesen einer JSON-Konfiguration.
Das verspottete Objekt ist das von der Funktion open () zurückgegebene io.TextIOWrapper-Objekt
quelle
Wenn Sie keine weitere Datei benötigen, können Sie die Testmethode dekorieren:
quelle