Soweit ich verstehe, Factory
und Proxy
Klassen werden im laufenden Betrieb durch den Autoloader erzeugt , wenn sie nicht existieren noch in var/generation
(siehe: Was die Erzeugung einer Fabrik in Magento Trigger 2 )
Aber warum erhalte ich diesen Fehler, wenn ich in einem Komponententest auf eine neue Fabrik verweise?
ReflectionException: Die Klasse Magento \ Framework \ Api \ Search \ SearchCriteriaBuilderFactory ist nicht vorhanden
[...] / vendor / magento / framework / TestFramework / Unit / Helper / ObjectManager.php: 161
use Magento\Framework\Api\Search\SearchCriteriaBuilderFactory;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
class SearchCriteriaTest extends \PHPUnit_Framework_TestCase
{
public function testFactoryGeneration()
{
$searchCriteriaBuilderFactory = (new ObjectManager($this))->getObject(SearchCriteriaBuilderFactory::class);
}
}
Ich benutze die Bootstrap-Datei dev/tests/unit/framework/bootstrap.php
.
Problemumgehungen Ich habe festgestellt, dass die Klasse generiert wird:
Verwenden des Real Object Managers (Danke @DigitalPianism):
\Magento\Framework\App\Bootstrap::create(BP, $_SERVER)->getObjectManager()->create('\Magento\Framework\Api\Search\SearchCriteriaBuilderFactory')
run
setup:di:compile
(vorausgesetzt, die Factory wird in einem Konstruktor referenziert)
Aber ich hoffe immer noch, eine saubere und performante Lösung zu finden.
Ich bin mir auch nicht sicher, ob es verwandt ist, aber create()
die vom Unit Test Object Manager generierte Factory kehrt zurück null
, sodass ich noch nicht einmal eine funktionierende Factory habe.
quelle
Magento\Framework\Api\Search\SearchCriteriaBuilder
?\Magento\Framework\App\Bootstrap::create(BP, $_SERVER)->getObjectManager()->create('\Magento\Framework\Api\Search\SearchCriteriaBuilderFactory');
?getObject
Sie nicht anrufengetBuilder
? Das sollte direkt übergetObject
aber nur zum Testen geschehen .Antworten:
Der einfachste Weg, damit umzugehen, besteht darin, die Kompilierung auszuführen, bevor Sie Tests ausführen:
Die andere Möglichkeit besteht darin, Methoden für das Factory-Mock explizit zu definieren, z. anstatt dies zu tun:
Mach das:
Irgendwann habe ich versucht, damit umzugehen, indem ich
ObjectManager::getObject
vor dem Erstellen eines Mocks angerufen habe , aber dies scheint keine saubere Lösung zu sein. Eine andere Sache ist, dass es nicht geholfen hat - es hat ein Objekt erstellt, aber die Klasse in var / generation nicht gespeichert. Ich habe mich nicht mehr damit befasst.quelle
Das Problem stammt aus der PHPUnit-Verspottungsbibliothek, da die benötigte Klasse nicht automatisch geladen werden kann.
Wenn Sie sich Magento dev repo ansehen, wird der Autoloader-Catcher eingerichtet, der auf Anforderung eine Klasse generiert. Wenn Sie eine ähnliche Bootstrap-Datei in Ihrem Modul-Repository erstellen, funktioniert dies recht gut: https://github.com/magento/magento2/blob/develop/dev/tests/unit/framework/autoload.php
Ich würde jedoch empfehlen, einen anderen Ansatz zu verwenden, indem Sie ein virtuelles Dateisystem verwenden, damit Ihre materialisierten generierten Klassen Ihren Build nicht beschädigen, wenn sich die Signatur der Schnittstelle der generierten Klassen ändert.
Und dann in Ihrer Bootstrap-Datei:
Ich habe einen ähnlichen Ansatz verwendet, als ich einen Adapter für PHPSpec https://github.com/EcomDev/phpspec-magento-di-adapter/blob/master/src/Extension.php#L98 erstellt habe
quelle
Sie können auch so etwas verwenden
und irgendwo im Code einfach weitergeben
quelle
$instanceName
und$factoryName
falls Sie eine Schnittstellenfactory haben, von der erwartet wird, dass sie Datenmodelle zurückgibt.