Gibt es eine Möglichkeit, unterschiedliche Scheinerwartungen für unterschiedliche Eingabeargumente zu definieren? Zum Beispiel habe ich eine Datenbankschichtklasse namens DB. Diese Klasse hat die Methode "Query (string $ query)". Diese Methode verwendet bei der Eingabe eine SQL-Abfragezeichenfolge. Kann ich für diese Klasse (DB) ein Modell erstellen und unterschiedliche Rückgabewerte für verschiedene Aufrufe von Abfragemethoden festlegen, die von der Eingabe-Abfragezeichenfolge abhängen?
117
Antworten:
Die PHPUnit Mocking-Bibliothek (standardmäßig) bestimmt, ob eine Erwartung nur anhand des an den
expects
Parameter übergebenen Matchers und der an übergebenen Einschränkung übereinstimmtmethod
. Aus diesem Grund schlagen zweiexpect
Aufrufewith
fehl , die sich nur in den übergebenen Argumenten unterscheiden , da beide übereinstimmen, aber nur einer das erwartete Verhalten aufweist. Siehe den Reproduktionsfall nach dem tatsächlichen Arbeitsbeispiel.Für Ihr Problem müssen Sie verwenden
->at()
oder->will($this->returnCallback(
wie in beschriebenanother question on the subject
.Beispiel:
Reproduziert:
Reproduzieren Sie, warum zwei -> with () -Aufrufe nicht funktionieren:
Ergebnisse in
quelle
$this->anything()
als einen der Parameter verwenden,->logicalOr()
um einen Standardwert für andere Argumente als dasjenige bereitzustellen, an dem Sie interessiert sind.Es ist nicht ideal zu verwenden,
at()
wenn Sie es vermeiden können, weil, wie ihre Dokumente behauptenSeit 4.1 können Sie
withConsecutive
zB verwenden.Wenn Sie möchten, dass es bei aufeinanderfolgenden Anrufen zurückkehrt:
quelle
Fatal error: Call to undefined method PHPUnit_Framework_MockObject_Builder_InvocationMocker::withConsecutive()
, der im Handumdrehen mit Composer auf 4.1 aktualisiert wurde und funktioniert.willReturnOnConsecutiveCalls
haben es getötet.Soweit ich herausgefunden habe, ist der beste Weg, um dieses Problem zu lösen, die Verwendung der Value-Map-Funktionalität von PHPUnit.
Beispiel aus der Dokumentation von PHPUnit :
Dieser Test besteht. Wie du siehst:
Soweit ich weiß , wurde diese Funktion in PHPUnit 3.6 eingeführt . Sie ist also "alt" genug, um in nahezu jeder Entwicklungs- oder Staging-Umgebung und mit jedem Tool für die kontinuierliche Integration sicher verwendet werden zu können.
quelle
Es scheint, dass Mockery ( https://github.com/padraic/mockery ) dies unterstützt. In meinem Fall möchte ich überprüfen, ob 2 Indizes in einer Datenbank erstellt wurden:
Spott, funktioniert:
PHPUnit, dies schlägt fehl:
Mockery hat meiner Meinung nach auch eine schönere Syntax. Es scheint ein bisschen langsamer zu sein als die in PHPUnits integrierte Verspottungsfunktion, aber YMMV.
quelle
Intro
Okay, ich sehe, dass es eine Lösung für Mockery gibt. Da ich Mockery nicht mag, werde ich Ihnen eine Prophezeiungsalternative geben, aber ich würde Ihnen empfehlen, zuerst über den Unterschied zwischen Spott und Prophezeiung zu lesen.
Lange Rede, kurzer Sinn: "Prophecy verwendet einen Ansatz, der als Nachrichtenbindung bezeichnet wird. Dies bedeutet, dass sich das Verhalten der Methode nicht im Laufe der Zeit ändert, sondern durch die andere Methode."
Problematischer Code der realen Welt
PhpUnit Prophecy Lösung
Zusammenfassung
Wieder einmal ist Prophezeiung fantastischer! Mein Trick besteht darin, die Nachrichtenbindung von Prophecy zu nutzen, und obwohl es leider wie ein typischer Rückruf-Javascript-Höllencode aussieht, beginnend mit $ self = $ this; Da Sie sehr selten Unit-Tests wie diesen schreiben müssen, denke ich, dass dies eine gute Lösung ist und es definitiv einfach ist, zu folgen, zu debuggen, da es tatsächlich die Programmausführung beschreibt.
Übrigens: Es gibt eine zweite Alternative, die jedoch eine Änderung des zu testenden Codes erfordert. Wir könnten die Unruhestifter einwickeln und sie in eine separate Klasse bringen:
könnte verpackt werden als:
und das war's, aber da ich keine weitere Klasse dafür erstellen wollte, bevorzuge ich die erste.
quelle