Jak dostat Nette\Caching\Cache do testeru?

Terka04
Člen | 44
+
0
-

Dobrý večer,
mám napsaný autotester, který spouští jednotlivé testy ze souborů. Tyto testy vycházejí z \Tester\TestCase. V testech mám zapnutý autoload a fungují bezvadně vč. napojení do databáze (databáze vychází Nette\Database). Nicméně nejsem schopna jakkoliv napojit cache a netuším, co dělám špatně. Cache mi jinak normálně v projektu fungují.

use Nette\Caching\Cache;

class testNeco extends Tester\TestCase {
	/** Cache **/
    /** @var Nette\Caching\Cache @inject */ public $cache;

	public funcion __construct() {
		// $this->cache je null
	}
}

Jak jinak mohu napojit cache? Zkoušela jsem i přes constructor a taktéž bez výsledku.

use Nette\Caching\Cache;

class testNeco extends Tester\TestCase {
	public funcion __construct(Nette\Caching\Cache $cache) {
		// $cache je null
	}
}

Pak jsem si s tím tak různě hrála, že jsem zkoušela všelijaké opičárny jdoucí proti všemu dobrému a také nic. Máte někdo zkušenosti?

Editoval Terka04 (14. 10. 2022 1:21)

Bulldog
Člen | 110
+
+2
-

Nejdřív se musíš naučit, jak funguje vstříknutí závislostí (DependencyInjection) a jakou roli v tom má DIC (Dependency Injection Container).

Jde o to, že ve výchozím stavu nic jako Inject ani DIC apod. neexistuje. To znamená, že každou jednotlivou instanci třídy musíš vytvářet pomocí new a do dalších instancí tříd je musíš explicitně předávat:

class testNeco extends Tester\TestCase {
	public funcion __construct(Nette\Caching\Cache $cache) {
		// $cache je null
	}
}

$journal = new Journal('Path');
$storage = new Storage('Directory', $journal);
$cache = new Cache($storage, 'namespace');
$test = new testNeco($cache);

Jenže toto psát pokaždé a ještě z toho mít duplicitu kódu je self-killing, takže se to dá na jedno místo, říkejme mu třeba Service Locator. No ale taky nechceš mít ten boilerplate kód s těmi spousty new, nějak to vytvářet, managovat atp.

Takže vytvoříš konfigurační soubor, který si ten náš Service Locator načte a sám podle toho bude zjišťovat, komu má co předat a kdy a taky kdy má kterou instanci třídy vytvořit. Nyní jsme z toho Service Locatoru udělali DIC. Ale DIC nemůže předávat závislosti instancím třídy, které sám netvoří. Jde o to, že nemáš možnost na pozadí nějak odposlouchávat každé new a pak instance automaticky plnit.
Jasně, že to svým způsobem jde, říká se tomu hooking, ale to je tak neintuitivní a skryté chování, že kdo to udělá dostane facana :D

Okay, takže máme objekt pojmenovaný DIC, kterému řekneš ‚hey dej mi objekt typu testNeco‘ a DIC ti řekne buď ‚Takový neznám sorry.‘ a nebo ti řekne ‚Jasně, tady ho máš i se všemi jeho závislostmi.‘ a o to vytvoření ostatních srand co potřebuje testNeco se postará on.

Takže máš vesměs 2 možnosti.

  1. Buď registrovat všechny testy do DIC a pak je získávat pomocí $dic->getByType(testNeco::class), což vstříkne i konstruktorové závislosti, nebo
  2. Vytvářet test ručně, ale pak do něj předat závislosti taky ručně i když třeba vytvořené přes DIC
$cache = $dic->getByType(Cache::class);
$testNeco = new testNeco($cache);

Jenom pamatuj na to, že NetteDIC nemá ve výchozím stavu Cache v sobě zaregistrovanou, jelikož čeká, že každá třída si bude Cache tvořit sama v závislosti, jaký v dané třídě chceš použít Storage a hlavně aby si mohla každá třída nastavit svůj namespace.

Pokud chceš nastavit jednotný namespace a storage globálně a tedy si předávat Cache přes DIC, tak tam tu cache musíš registrovat podle dokumentace.

Terka04
Člen | 44
+
0
-

Bulldog napsal(a):

Nejdřív se musíš naučit, jak funguje vstříknutí závislostí (DependencyInjection) a jakou roli v tom má DIC (Dependency Injection Container).

Jsi bůh! Děkuji moc za obsáhlý článek. Je pravda, že jsem se ani nepídila, jak to funguje, prostě jsem chtěla použít něco, co neexistovalo. :( Po několika dnech boje se mi to podařilo napojit pár řádky. ♥

Bulldog
Člen | 110
+
0
-

Jsem rád, že se povedlo. :)