Testovani Repository a inject jine tridy
- martin28
- Člen | 40
Ahoj, potrebuji pomoci. Nevim zda je navrh projektu uplne idealni, ale takto byl postaven a tedka nad to pisi testy.
v testu mam
chyba
Error: Call to a member function getItemsPolozky() on null
asi to zpusobuje ze to neinjectuje tu SablonyImportRepository. Jak toto vyresit?
A prosim prepisovat aplikaci, nejde!
Dekuji Martin
- Polki
- Člen | 553
Souhlas s klukama. Udělej to jednotně.
Co ale nechápu ještě víc je, proč sakra taháš
ObjednavkaRepository
z DI kvůli testům? Máš testovat
ObjednavkaRepository
, nebo DIC? :D
Pokud ObjednavkaRepository
, tak je zbytečné tahat celý DIC a
kdo ví co z něj tahat a tvořit za služby, tak opravdu testuj jen tu třídu
ObjednavkaRepository
například takto:
Tím, že si vytvoříš mock ke každé té třídě, co je jako závislost
docílíš toho, že se connection nebude doopravdy dotazovat do databáze a
sablony_import nebude opravdu něco importovat.
Díky tomu docílíš toho, že se na pozadí neudělají side-efekty a hlavně
otestuješ opravdu jen a jen třídu ObjednavkaRepository
a nic
jiného.
Vem si příklad, že by jsi testoval platební bránu. Na testu to je ok, jelikož se připojí na testovací rozhraní a nic ti to nestrhne. Co když se ale náhodou spustí testy nějaký blázen na produkci, kde je jako závislost nastavena produkční verze připojení naostrou platební bránu a je tam nastaven nějaký systém opakované platby? To by to najednou všem zákazníkům strhlo peníze za opakovanou platbu například, i když by nemělo. A to je průser jako prase.
Řešení je opět to, co jsem napsal:
Tak to bychom měli vytvořenou aplikaci. Ale abych otestoval třídu
OrderCron
, tak se nemusím připojovat do databáze ani dělat
dotaz na platební bránu. Udělám tedy toto (všechny třídy jsou teď
reálně napsané, jak by vypadaly testy a ne pseudokod, jako nahoře.):
S mockama je pak testování elegantnější. Hlavně jak vidíš, tak se
v mockách nedělají žádné side-efekty. Problém může nastat v tom, že
psát takové mocky můžebýt zdlouhavé, a pak takové, že by i mock
potřeboval testy a to je špatně a v neposlední řadě to, že třeba z
Nette\Database\Explorer
mock neuděláš, protože nemá nějaký
globálně přístupný interface, takže by sis musel nad tím buď vytvořit
nějaký adapter, fasádu, proxy atp., podle typu, kterou by jsi udělal tak,
aby už šla mockovat. A to v tvém případě nejde jak píšeš.
Ale existuje jiná cesta. Někdo vymyslel mocnou knihovnu Mockery, která to vše udělá za tebe a ty se nestaráš. Moje mocky+testy by s pomocí mockery vypadaly takto:
Jak vidíš, tak s použitím knihovny Mockery se mockované třídy tvoří skoro samy, není k tomu třeba řešit závislosti a hlavně MOCKY NEDĚLAJÍ SIDE-EFEKTY a nemusíš natahovat další závislosti a tvořit celý DIC…
Tvůj dotaz by byl otestován ± takto:
Easy, clear and nice.
Editoval Polki (7. 5. 2022 8:53)