Here is the method to test.
public function performPoolRequest(RecreationRequestsCollection $requests): RecreatedPaymentsPoolReading
{
$count_request = count($requests);
if($count_request) {
$pool_recreate_payments = new RecreatedPaymentsPool();
$this->http_client->sendPoolRequest(
$this->generateRequests($requests),
$count_request,
function (ResponseInterface $response, $index) use ($requests, $pool_recreate_payments) {
$this->successHandler($response, $requests, $index, $pool_recreate_payments);
},
function (BadResponseException $reason, $index) use ($requests, $pool_recreate_payments) {
$this->failureHandler($reason, $requests, $index, $pool_recreate_payments);
}
);
return $pool_recreate_payments;
} else {
throw new PoolRequestException('Incorrect amount of requests: ' . $count_request);
}
}
Difficulties arose with this piece of code:
$this->http_client->sendPoolRequest(
$this->generateRequests($requests),
$count_request,
function (ResponseInterface $response, $index) use ($requests, $pool_recreate_payments) {
$this->successHandler($response, $requests, $index, $pool_recreate_payments);
},
function (BadResponseException $reason, $index) use ($requests, $pool_recreate_payments) {
$this->failureHandler($reason, $requests, $index, $pool_recreate_payments);
}
);
I made a mock object $this->http_client
But I don't know how to test methods in the argumets ($this->successHandler, $this->failureHandler, this->generateRequests($requests)) that are sent to the method sendPoolRequest.
All of these methods are protected. I understand how to test them using a reflection object, but I want to know if there is an option to test them within a single test by checking the values in $ pool_recreate_payments.
You have to fake what the http client is doing in some way. That means: actually calling the callback functions. While it might be possible to do that with a PHPUnit mock object, writing own test doubles is often easier.
Here are a few examples to get you started.
public function testAllFailing()
{
$client = new class implements HttpClient {
public function sendPoolRequest(array $requests, int $numRequests, callable $successHandler, callable $errorHandler)
{
foreach ($requests as $index => $request) {
$errorHandler(new BadResponseException(/*...*/), $index);
}
}
};
$myService = new MyService($client);
$result = $myService->performPoolRequest(/*...*/);
self::assertEquals(/*...*/, $result);
}
public function testAllSucceeding()
{
$client = new class implements HttpClient {
public function sendPoolRequest(array $requests, int $numRequests, callable $successHandler, callable $errorHandler)
{
foreach ($requests as $index => $request) {
$successHandler(new Response(/*...*/), $index);
}
}
};
$myService = new MyService($client);
$result = $myService->performPoolRequest(/*...*/);
self::assertEquals(/*...*/, $result);
}
public function testEveryOtherFails()
{
$client = new class implements HttpClient {
public function sendPoolRequest(array $requests, int $numRequests, callable $successHandler, callable $errorHandler)
{
foreach ($requests as $index => $request) {
if ($index % 2 === 0) {
$successHandler(new Response(/*...*/), $index);
} else {
$errorHandler(new BadResponseException(/*...*/), $index);
}
}
}
};
$myService = new MyService($client);
$result = $myService->performPoolRequest(/*...*/);
self::assertEquals(/*...*/, $result);
}
Since Guzzle is used as the http client, I decided to use its capabilities in terms of creating stubs for the response object. Here is a link to the documentation Guzzle documentation. The solution turned out to be simple and allowed us to extensively test the business logic of the response.
I try to give '$_REQUEST['vider']' to an other controller like this :
return $this->forward('TestBundle:Rapport:bo', array('vider' => 'vider'));
//, array ($_REQUEST['vider'] => 'vider) doesn't work too
But in my function Rapport:bo, $_REQUEST['vider'] is null, i give it in the array, where i failed ?
edit :
my Rapport:bo function :
public function boAction(Request $request) {
var_dump($_REQUEST['vider']); // is null
if ( isset($_REQUEST['vider']) ) ) {
var_dump('test');
}
}
Try with:
public function boAction($vider) {
your logic...
Please i need some help:
I have the following services:
SERVICE CONFIGURATION IN services.yml
services:
xpad.producto_repository:
class: Xpad\ProductoBundle\Entity\ProductRepository
factory_service: doctrine.orm.clientes_entity_manager
factory_method: getRepository
arguments:
- Xpad\ProductoBundle\Entity\Product
backend_cliente.producto_filters:
class: Xpad\BackendClienteBundle\Filters\ProductFilters
calls:
- [setRepository, ["#xpad.producto_repository="]]
scope: container
AND THE CLASS FOR backend_cliente.producto_filters IS:
namespace Xpad\BackendClienteBundle\Filters;
use Xpad\ProductoBundle\Entity\ProductRepository;
class ProductFilters
{
private $_queryBuilder;
public function getQueryBuilder()
{
return $this->_queryBuilder;
}
public function setQueryBuilder($queryBuilder)
{
$this->_queryBuilder = $queryBuilder;
}
public function setRepository(ProductRepository $productRepository = null)
{
if($this->_queryBuilder == null)
{
$this->_queryBuilder = $productRepository->createQueryBuilder('p');
}
}
}
AND I HAVE THE FOLLOWING ACTION IN ONE OF MY CONTROLLERS:
class ProductController extends Controller
{
............
public function indexAction(Request $request)
{
//SOME CODE
$service_filter = $this->container->get('backend_cliente.producto_filters');
$queryBuilder = $service_filter->getQueryBuilder();
//SOME OTHER CODE
}
MY PROBLEM IS: ANYTIME THAT THE indexAction is execute I GOT A NEW INSTANCE OF backend_cliente.producto_filters SERVICE AND I DON'T KNOW WHY. I NEED AND UNIQUE INSTANCE AS A SINGLETON BECAUSE A HAVE THE $_queryBuilder ATRIBUTTE AND I NEED TO GET THE VALUE OF IT JUST MODIFY ITS VALUE WHEN IS NEEDED;
PLEASE HELP I DON KNOW WHAT I'M DOING WRONG.
Do you have to use the class as a service?
Why don't you use a Singleton, without using a service? Like this:
namespace Xpad\BackendClienteBundle\Filters;
use Xpad\ProductoBundle\Entity\ProductRepository;
class ProductFilters {
private $_queryBuilder;
private static $reference = null;
public function getInstance(){
if (self::$reference === null)
self::$reference = new ProductFilters();
return self::$reference;
}
private function __construct(){}
public function getQueryBuilder()
{
return $this->_queryBuilder;
}
public function setQueryBuilder($queryBuilder)
{
$this->_queryBuilder = $queryBuilder;
}
public function setRepository(ProductRepository $productRepository = null)
{
if($this->_queryBuilder == null)
{
$this->_queryBuilder = $productRepository->createQueryBuilder('p');
}
}
}
And call it with:
...
$filter = ProductFilters::getInstance();
...
I need to get a parameter value in my following twig extension class
namespace xxxx\WebBundle\Twig;
use Symfony\Component\HttpKernel\KernelInterface;
class MyExtension extends \Twig_Extension
{
public function getFilters()
{
return array(
new \Twig_SimpleFilter('affliate', array($this, 'urlFilter')),
);
}
public function urlFilter($url,$aff)
{
$separator = "?";
if (strpos($url,"?")!=false) {
$separator = "&";
}
$parse = parse_url($url);
//echo $parse['host'];
$app_url = $url.$separator.'tag='.$aff;
return $app_url;
}
public function getName()
{
return 'wishbot_extension';
}
}
In controller we can use like this $this->container->getParameter('contact_email');
But I need the value in twig extension class.
Inject the parameters as arguments into your twig extensions's constructor like this:
config.yml
services:
twig.extension.your_extension:
class: Vendor\YourBundle\Twig\Extension\YourExtension
arguments: [ %parameter1%, %parameter2% ]
tags:
- { name: twig.extension }
YourExtension.php
protected $parameter1;
protected $parameter1;
public function __construct($parameter1, $parameter2)
{
$this->parameter1 = $parameter1;
$this->parameter2 = $parameter2;
}
// ....
public function urlFilter($url,$aff)
{
// access the parameters using $this->parameter1
}
I have implemented a new twig extension and I have some text which had to be translated.
Unfortunately when I use a code label it appears as a sample text.
I mean when twig render this following extension, it displays: 5 entity.years instead of 5 years for example:
class MyExtension extends \Twig_Extension {
public function getFilters()
{
return array(
'myextension' => new \Twig_Filter_Method($this, 'myextension'),
);
}
public function myextension ($myId)
{
// ....
// Some operations concerning $myId...
// ....
if($myId!=0) {
$res = $myId. ' '.'entity.year';
} else {
$res = ($months == 0 ? $days.'entity.days' : $months.'entity.months');
}
return $res;
}
}
Where entity.years, entity.months, entity.days is defined into my translations folder.
Inject the translator service into your extension and use it. For example:
class MyExtension extends \Twig_Extension
{
private $translator;
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
// ...
public function myMethod()
{
return $this->translator->trans('my_string');
}
}