Ich bin neu zu testen und schreiben testbaren Code, und bin auf der Suche nach einigen Erklärungen über die richtige Art und Weise mit diesem einfachen Szenario umzugehen. Ich habe andere Fragen und Antworten zu SO mit ähnlichen Titeln gelesen, aber sie scheinen keine klare Antwort auf meine Frage zu geben.Wie Unit-Test-Modell-Methode, die Methode auf einem anderen Modell in Laravel ruft
Ich habe einen Controller, der die shipped()
Methode auf einer Instanz von meiner Picking
Klasse ruft:
class MyController extends \BaseController {
public function controllerMethod() {
$picking = new Picking;
$picking->shipped($shipmentData);
}
}
Das Picking
Modell sieht wie folgt aus:
class Picking extends \Eloquent {
public function order() {
return $this->belongsTo('Order');
}
public function shipped($shipmentData) {
$this->carrier = $shipmentData['Carrier'];
$this->service = $shipmentData['Service'];
$this->is_shipped = true;
$this->save();
$this->order->pickingShipped();
}
}
Wie Sie sehen können, diese shipped()
Methode speichert einige Daten und ruft dann die pickingShipped()
-Methode auf, es ist Order
verwandt.
Jetzt versuche ich, einen Test für die shipped()
Methode zu schreiben, und ich bin mir nicht sicher, der geeignete Weg, dies zu tun. Ich habe über Spott gelesen, aber ich bin verwirrt, wenn dies eine Situation ist, in der Spott notwendig ist. Ich habe an einige mögliche Lösungen gedacht, aber ich bin mir nicht sicher, ob einige von ihnen richtig sind.
1) Ordnen Sie den Code so an, dass der Controller die pickingShipped()
-Methode aufruft, wodurch er aus der shipped()
-Methode entfernt werden kann, wodurch der Test vereinfacht wird.
Zum Beispiel würde die letzte Zeile des shipped()
Verfahrens entfernt werden, und der Controller-Code würde sich ändern:
$picking = new Picking;
$picking->shipped($shipmentData);
$picking->order->pickingShipped();
2) Bei dem Test auf order
ein mock Verfahren so, dass die Verwendung Test kann einfach bestätigen, dass die pickingShipped()
Methode aufgerufen wird.
Etwas in der Richtung was erklärt wird here. Das würde bedeuten, den Test so etwas tun könnte:
$order->expects($this->once())->method('pickingShipped')
Aber ich denke, das würde bedeuten, dass ich auch eher die Reihenfolge Abhängigkeit zu injizieren als unter Berufung auf die order
Beziehung innerhalb des shipped()
Methode, wie folgt aus:
class Picking extends \Eloquent {
public function order() {
return $this->belongsTo('Order');
}
public function shipped(Order $order, $shipmentData) {
$this->carrier = $shipmentData['Carrier'];
$this->service = $shipmentData['Service'];
$this->is_shipped = true;
$this->save();
$order->pickingShipped();
}
}
Und dann der Code in der Steuerung würde wie folgt aussehen haben:
$picking = new Picking;
$picking->shipped($picking->order, $shipmentData);
das fühlt sich ein wenig stran ge, aber ich bin mir wirklich nicht sicher, was richtig ist.
Meine Frage ist, was ist der richtige Weg, um diesen Code zu schreiben und zu testen? Es ist einfach zu testen, die shipped()
Methode setzt die entsprechenden Daten auf sich selbst, aber was ist mit diesem Anruf an pickingShipped()
am Ende? Dies scheint die Tests komplizierter zu machen. Soll der Code also neu geordnet werden? Wenn das so ist, wie? Oder ist das ein häufiger Anwendungsfall für Spott, wie ich es in der 2. Option umschrieben habe? Wenn ja, ist es richtig, die Abhängigkeit zu injizieren, wie ich es zeige?
Danke für die Rückmeldung! Mein einziges Problem bei diesem Ansatz besteht darin, dass wir zulassen, dass eine '$ order' in die Methode übernommen wird, obwohl dies in der Realität nicht erlaubt sein sollte. Der Sinn der Methode ist, dass sie 'PickingShipped' auf der Kommissionierreihenfolge aufrufen muss, nicht auf irgendeiner Bestellung. Das bedeutet, dass wir diesen Parameter nur zu Testzwecken hinzufügen. Es ist seltsam, die Methodensignatur nur zu Testzwecken zu ändern. Jetzt schlägt die Methode vor, dass es für ein Verhalten verwendet werden sollte, das es eigentlich nicht sollte. – flyingL123
In Bezug auf Standardargumente können Sie mit yes PHP übergeben, aber sie können keinen dynamischen Wert wie '$ this-> order' haben. In diesem Fall würde ich den Standardwert auf "null" setzen und dann am Anfang der Methode sagen: if (is_null ($ order)) $ order = $ this-> order; ', was dasselbe bewirkt, aber wie ich oben sagte, fühlt sich diese Abhängigkeitsinjektion immer noch nicht richtig an. – flyingL123