2017-09-19 4 views
0

Ich benutze unittest.mock, diese wunderbare Bibliothek. Ich war jedoch überrascht von einem unerwarteten Verhalten, und ich sehe keine offensichtliche Lösung. Ich benutze es für meine Komponententests und es ist wichtig zu verstehen, wie es sich verhält, um nützliche Tests zu haben.Wie testet man, ob die Methode der Instanz beim Spotten mit "self" aufgerufen wird?

Ich weiß, der Code unten in show_bar ist kaputt, es ruft eine Klassenmethode anstelle der Instanzmethode. Doch alle meine mockUnittests sind vorbei:

-Code einen Fehler enthält,:

class Foo(object): 
    def bar(self): 
     return "bar" 

    def show_bar(self): 
     return Foo.bar() 

Erwartete Nutzung:

foo = Foo() 
assert foo.show_bar() == "bar" 
# => throw exception: bar() missing 1 required positional argument: 'self' 

Unittest erfolglos versucht, diesen Fehler zu fangen mock:

from unittest.mock import patch 
with patch.object(Foo, 'bar', return_value="bar") as mock: 
    foo = Foo() 
    assert foo.show_bar() == "bar" 
mock.assert_called_once() 
# => no errors 

Im Idealfall würde Ich mag zu behaupten dass bar mit self.bar() genannt und nicht Foo.bar(); was falsch ist. Leider berücksichtigt die Verwendung von mock.assert_called_with() nicht die self noch cls Parameter, also bin ich ein bisschen verwirrt.

BEARBEITEN: Versuchen zu klären. Ich suche nach Best Practices, um die Bibliothek unittest.mock zu verwenden, wenn wir die Methode eines Objekts patchen müssen. Es scheint mir nicht klar zu sein, wie man es patcht, derzeit habe ich keine Möglichkeit zu behaupten, wenn es self.bar oder Foo.bar ruft.

+0

nichts spotten Sie, rufen Sie einfach 'f = Foo(); f.bar() 'in deinem Testcode. Bei der fehlerhaften Implementierung wird ein 'TypeError' ausgelöst, der den Test fehlschlagen lässt. –

+0

Auch und FWIW, das hat nichts mit 'classmethod' zu tun - in Ihrem Beispiel ist' Foo.bar' eine ungebundene Instanzmethode. –

+0

Entschuldigung, der Code ist zu stark vereinfacht und ich * brauche * zu verwenden, da der tatsächliche Code der Methode nicht aufrufbar ist, ohne seinen Rückgabewert zu verspotten. Wenn "show_bar" den Entwickler 'Foo.bar()' aufruft, nahm ich an, dass 'Foo.bar' entweder eine Klassenmethode oder eine statische Methode ist. Es scheint eine vernünftige Aussage zu sein? – Doomsday

Antwort

1

Ich verstehe nicht wirklich, warum Sie die Methode verspotten sollten, um zu testen, dass es kein TypeError beim Aufruf ausgelöst wird, aber trotzdem ... Jemand anders könnte erklären, wie man dies unter Verwendung unittest.mock in der Zwischenzeit lösen kann nur unittest.mock und Mock Foo.bar selbst überspringen:

callargs = dict() 
def mock_bar(self): 
    callargs["self"] = self 
    return "bar" 

foobar = Foo.__dict__["bar"] 
Foo.bar = mock_bar 
try: 
    foo = Foo() 
    assert foo.show_bar() == "bar" 
    assert "self" in callargs 
    assert callargs["self"] is foo 
finally: 
    Foo.bar = foobar 
+0

Eigentlich versuche ich nicht mein Problem zu lösen, was trivial ist, weder "manuell" meine Klasse verspotten, ich suche nur nach "unittest.mock" korrekt zu ersetzen Methodenaufrufe in unittesting Kontext. Danke, dass du versucht hast zu helfen! – Doomsday

Verwandte Themen