Angenommen, das folgende Szenario:
- Ich habe eine Klasse, die einen externen Dienst anruft
- Die Klasse implementiert eine Schnittstelle und ist als bevorzugte Implementierung für diese Schnittstelle in definiert
di.xml
- Ein Block empfängt diese Schnittstelle als Konstruktorparameter
- Ich möchte eine Magento-Anfrage in einem Integrationstest testen, der diesen Block verwendet
Ich möchte den externen Dienst nicht anrufen, deshalb möchte ich mich über diese Klasse lustig machen und mich fragen, wie das am besten geht.
Ich weiß, dass Sie DI-Einstellungen im laufenden Betrieb mit definieren können
$objectManager->configure(
['preferences' => [TheInterface::class => MockClass::class]]
);
Dafür muss jedoch selbst eine Mock-Klasse definiert MockClass
werden. Ich kann kein PHPUnit-Mock-Objekt verwenden.
Dies funktioniert in Ordnung, wenn die injizierte Klasse eine Factory ist, da ich eine Mock-Factory erstellen kann, die das eigentliche Mock-Objekt erstellt.
Aber ist das der einzige Weg oder fehlt mir etwas?
Aktualisieren:
Die vorgeschlagene Methode
$objectManager->addSharedInstance($mock, TheInterface::class);
sah zuerst gut aus, funktionierte aber nur, solange keine Präferenzen definiert waren. Diese haben Vorrang vor gemeinsam genutzten Instanzen.
Ich habe versucht, die Einstellung dynamisch zu entfernen:
$this->objectManager->configure(
['preferences' => [TheInterface::class => null]]
);
Leider ruft Magento ltrim($to, '\\')
das Argument auf, das es in eine leere Zeichenfolge konvertiert. Das führt zu:
ReflectionException: Klasse existiert nicht
quelle
di.xml
ist, die Voreinstellung jedoch Vorrang vor der gemeinsam genutzten Instanz zu haben scheint.$this->objectManager->addSharedInstance($mockedLogger, 'CustomLogger');
. Das zu wissen hätte mir eine Stunde gespart :-P