Ich habe eine Einstiegspunktfunktion es auf ein Objekt main
nennen, die ich unmocked bleiben möchte, da es mehrere andere Methoden für das Objekt aufruft:Wie packe ich ein Objekt, so dass alle Methoden außer einem verspottet werden?
class Thing(object):
def main(self):
self.alpha()
self.bravo()
def alpha(self):
self.charlie()
def bravo(self):
raise TypeError("Requires Internet connection!")
def charlie(self):
raise Exception("Bad stuff happens here!")
Das ist ziemlich geradlinig manuell zu verspotten:
thing = Thing()
thing.alpha = MagicMock()
thing.bravo = MagicMock()
und ich kann sicherstellen testen, dass alpha und bravo beide einmal genannt, kann ich Nebenwirkungen in alpha und bravo auf sicherzustellen, dass sie behandelt, etc. etc.
Was ich bin besorgtes Abo ut ist, wenn sich die Code-Definition ändert und jemand einen charlie
Aufruf an main
hinzufügt. Es wird nicht gespottet, also werden die Nebenwirkungen spürbar (und sie sind Dinge wie das Schreiben in eine Datei, das Verbinden mit einer Datenbank, das Holen von Sachen aus dem Internet, so dass eine einfache Ausnahme mich nicht darauf aufmerksam macht, dass die Tests jetzt sind Schlecht).
Mein Plan war zu überprüfen, dass mein Mock-Objekt keine anderen Methoden aufruft als die, die ich sagen soll (oder eine Testausnahme auslösen). Allerdings, wenn ich so etwas tun:
MockThing = create_autospec(Thing)
thing = Thing()
thing.main()
print thing.method_calls
# [calls.main()]
Dann wird main
auch verspottet, so dass es keine anderen Methoden aufruft. Wie kann ich jede Methode, aber die Hauptmethode vortäuschen? (Ich möchte, dass method_calls [calls.alpha(), calls.bravo()]
ist).
Edit: Für Hacking Antworten
Nun habe ich eine wirklich hacky Lösung, aber ich hoffe, es gibt eine bessere Antwort als diese. Grundsätzlich rebind ich die Methode von der ursprünglichen Klasse (Python bind an unbound method)
MockThing = create_autospec(Thing)
thing = MockThing()
thing.main = Thing.ingest.__get__(thing, Thing)
thing.main()
print thing.method_calls
# [calls.alpha(), calls.bravo()]
Aber es hat eine einfachere Lösung sein, als Funktion Deskriptoren!
Ich bekomme Fehler "Objekt hat kein Attribut 'ingest", irgendeine Idee, was das verursacht? Ich benutze Python 2.7 –