Jak dostat Nette\Caching\Cache do testeru?
- Terka04
- Člen | 44
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
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.
- 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 - 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
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. ♥