Ich benutze mock with Python und habe mich gefragt, welcher dieser beiden Ansätze besser ist (sprich: mehr Pythonic).
Methode eins : Erstellen Sie einfach ein Scheinobjekt und verwenden Sie dieses. Der Code sieht so aus:
def test_one (self):
mock = Mock()
mock.method.return_value = True
self.sut.something(mock) # This should called mock.method and checks the result.
self.assertTrue(mock.method.called)
Methode zwei : Verwenden Sie Patch, um ein Mock zu erstellen. Der Code sieht so aus:
@patch("MyClass")
def test_two (self, mock):
instance = mock.return_value
instance.method.return_value = True
self.sut.something(instance) # This should called mock.method and checks the result.
self.assertTrue(instance.method.called)
Beide Methoden machen dasselbe. Ich bin mir der Unterschiede nicht sicher.
Könnte mich jemand aufklären?
mock.patch
ist ein ganz anderes Lebewesen als mock.Mock
. patch
ersetzt die Klasse durch ein Scheinobjekt und lässt Sie mit der Scheininstanz arbeiten. Schauen Sie sich diesen Ausschnitt an:
>>> class MyClass(object):
... def __init__(self):
... print 'Created [email protected]{0}'.format(id(self))
...
>>> def create_instance():
... return MyClass()
...
>>> x = create_instance()
Created [email protected]
>>>
>>> @mock.patch('__main__.MyClass')
... def create_instance2(MyClass):
... MyClass.return_value = 'foo'
... return create_instance()
...
>>> i = create_instance2()
>>> i
'foo'
>>> def create_instance():
... print MyClass
... return MyClass()
...
>>> create_instance2()
<mock.Mock object at 0x100505d90>
'foo'
>>> create_instance()
<class '__main__.MyClass'>
Created [email protected]
<__main__.MyClass object at 0x100505d90>
patch
ersetzt MyClass
auf eine Weise, mit der Sie die Verwendung der Klasse in von Ihnen aufgerufenen Funktionen steuern können. Sobald Sie eine Klasse patchen, werden Verweise auf die Klasse vollständig durch die Scheininstanz ersetzt.
mock.patch
wird normalerweise verwendet, wenn Sie etwas testen, das eine neue Instanz einer Klasse innerhalb des Tests erstellt. mock.Mock
Instanzen sind klarer und werden bevorzugt. Wenn dein self.sut.something
Methode erstellt eine Instanz von MyClass
anstatt eine Instanz als Parameter zu erhalten, dann mock.patch
wäre hier angebracht.
Ich habe ein YouTube-Video dazu.
Kurze Antwort: Verwenden Sie mock
, wenn Sie das Objekt übergeben, das Sie verspotten möchten, und patch
, wenn Sie dies nicht tun. Von den beiden ist Mock stark bevorzugt, da dies bedeutet, dass Sie Code mit der richtigen Abhängigkeitsinjektion schreiben.
Dummes Beispiel:
# Use a mock to test this.
my_custom_Tweeter(Twitter_api, sentence):
sentence.replace('cks','x') # We're cool and hip.
Twitter_api.send(sentence)
# Use a patch to mock out Twitter_api. You have to patch the Twitter() module/class
# and have it return a mock. Much uglier, but sometimes necessary.
my_badly_written_Tweeter(sentence):
Twitter_api = Twitter(user="XXX", password="YYY")
sentence.replace('cks','x')
Twitter_api.send(sentence)