Mam nadzieje, że mnie zrozumiecie. Otóż mam problem z testowaniem service . Te service ma parametry , które są wstrzykiwane . Znów te service składa się 2 następnych service (bo one tam do tego głównego service są wstrzykiwane).
Te 2 następne service znów mają jakieś elementy wstrzykiwane . I irytuje mnie to , że muszę jawnie tak wrzucać paramtery / obiekty, bo w testach nie można wstrzykiwać. Czy istnieje jakiś sposób aby to obejść?
Nie do końca rozumiem Twój problem ale wydaje mi się, że wystarczy jak użyjesz np:
$argument1 = $this->getMockBuilder(Service1::class) ->disableOriginalConstructor() ->getMock(); $argument2 = $this->getMockBuilder(Service2::class) ->disableOriginalConstructor() ->getMock(); $argument3 = $this->getMockBuilder(Service3::class) ->disableOriginalConstructor() ->getMock(); $service = new Service( $argument1, $argument2, $argument3 );
No super . Dzięki. A wiesz może jak przetestować funkcję , która używa danych z requesta? Bo wtedy test mi wrzuca błąd ponieważ żadne dane nie są wysyłane?
Nie wiem , czy wiesz o co chodzi .
Mam tutaj dla przykładu kawałek klasy service:
class FetchMsgSql { protected $entityManager; protected $qb; protected $parameters; protected $array_par; private $requestStack; public function __construct(EntityManager $em, RequestStack $requestStack) { $this->requestStack = $requestStack; $this->entityManager = $em; $this->qb = $em->createQueryBuilder(); } // create results based on data from the request table // converting data to the form of query public function getSql() { $this->qb->select('a')->from('AppBundle:Cars', 'a'); // starts the build_condition function if a query was sent from the searchAction action and the knppaginaton object uses the search function // search == 1 -> when you view the pages by knppagination and knppagination is supposed to store the results // search == 1 -> results from the request table are attached during the search engine save in the sortable_link.html view (($this->requestStack->getCurrentRequest()->query->get('search') == "1") || ($this->requestStack->getCurrentRequest()->getRealMethod() == 'POST') ) ? $this->qb->setParameters($this->build_condition()) : NULL; $dql = $this->qb->getQuery()->getDQL(); //< convert the dql object to the query form foreach ($this->qb->getParameters() as $index => $param) { $dql = http://www.php.net/str_replace(":" . $param->getName(), $param->getValue(), $dql); $dql = http://www.php.net/str_replace("LIKE " . $param->getValue(), "LIKE '" . $param->getValue() . "'", $dql); } // > $query = $this->entityManager->createQuery($dql); return $query; }
Według mnie powinieneś zamockować po prostu tą metodę z odpowiednio zwracanymi danymi które są używane gdzieś dalej, nie widzę sensu abyś miał łączyć się do bazy danych itd aby przetestować Ją samą.
Ale jak chciałbyś utworzyć te parametry to musiałbyś zrobić mniej więcej tak:
$requestStack = new RequestStack(); $requestStack->getCurrentRequest()->setMethod('POST') $requestStack->getCurrentRequest()->query->set('search', 1);
1) Robiac Mock klasy request mozesz okreslic co maja zwracac dane metody a tym samym mozesz zasymulowac przeslanie parametrow z POST
2) Moim zdaniem masz zle zaprojektowana te klase bo jest ona zalezna od request. Bardziej metoda getSql powinna jako parametr przyjmowac tablice i tam powinienies ustawiac dane z request. Wowczas uniezalezniasz sie od klasu request, twoj service moze dzialac na danych z dowolnego zrodla i bez problemu jestes to w stanie przetestowac
ps:
$dql = str_replace(":" . $param->getName(), $param->getValue(), $dql);
$dql = str_replace("LIKE " . $param->getValue(), "LIKE '" . $param->getValue() . "'", $dql);
Ouch, czemu tak?
Używam knpbundle a on niestety potrzebuje dane trochę bardziej przekowertowane. Zresztą dużo by mówić, po prostu jest coś gdzieś w kodzie kombinowane.
Jeśli tak uważasz, to postaram się to pozmieniać w przyszłości i zmienić trochę model tego. Uważam, że masz racje i źle to zrealizowałem .
Chyba masz racje, nie będę tego testował. Mam słabe doświadczenie w programowaniu i po prostu się uczę testować moją aplikację ;-)
Call to a member function setMethod . Funkcja ta niestety nie działa :-(
A jaka dokładnie wersja Symfony ?
symfony 3.4 . Jakoś nie łapie tego request.Ponieważ jak sprawdzam var_dump($requestStack->getCurrentRequest()) to zwraca mi NULL ale tylko w kodzie testach. A normalnie w kodzie aplikacje zwraca obiekt request. Może coś w kernellu trzeba ustawić?
To spróbuj zrobić coś takiego:
$request = new Request(['search' => 1],null,null,null,null,['REQUEST_METHOD' => 'POST']); $requestStackMock = $this->getMockBuilder(RequestStack::class) ->disableOriginalConstructor() ->getMock(); $requestStackMock->expects($this->any())->method('getCurrentRequest')->willReturn($request);
@rad11 Ale po co tak kombinować?
Tak długo jak długo nie trzeba używać żadnych mocków powinno się od nich uciekać. Request / RequestStack to bardzo proste obiekty, które spokojnie można tworzyć sobie na potęgę.
$request = new Request(...); $requestStack = new RequestStack(); $requestStack->push($request);
To że w produkcyjnym kodzie te kryteria będą gdzieś, jakoś budowane na podstawie danych z żądania HTTP nie ma znaczenia dla tej klasy - ona ma się skupić na swoim zadaniu czyli budowaniu odpowiedniego zapytania na podstawie odpowiednich kryteriów. Ten kod strasznie łatwo przetestujesz i co więcej może to być wartościowy test! A co z tą kwestią tworzenia obiektu reprezentującego kryteria? To jest inna część kodu - może być inicjowana gdzieś pewnie na poziomie jakiegoś kontrolera, która powinna być poddana osobnemu testowi - który weryfikuje jedynie czy obiekt kryteriów jest prawidłowo tworzony na podstawie obiektu żądania HTTP.
class AbcSearchCriteria { private string $name; private string $value; public __construct(string $name, string $value) { ... } public getName() { return $this->name; } public getValue() { return $this->value; } } class AbcSearchQueryBuilder { public __construct($em, ...) public buildQuery(AbcSearchCriteria $criter) { ... } }
rozumiem o co Tobie chodzi . No ale mam słabe doświadczenie w programowaniu a już sam fakt , że źle zacząłem, że dopiero podchodzę teraz do testów to już z tego wynikają błędy. Teraz sam to widzę
Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)