pass route paramerter in testcase - phpunit

I am writing a testcase in which i have to send parameter as we pass in route. Here is my controller.
class TestingControll extends Controller {
public function addTestUsingParameters(Response $response)
{
$firstNum = $response->firstNum ;
$secondNum = $response->secondNum ;
$sumOfNumbers = $firstNum + $secondNum;
return $sumOfNumbers;
}
}
Here is my route
Route::get('test/cal/{firstNum}/{secondNum}', array('as' => 'testCal', 'uses' => 'TestingControll#addTestUsingParameters'));
Here is my Testcase code.
class CalculatorTest extends TestCase {
public function testCanAddNumbers()
{
$calcu = $this->action('GET','TestingControll#addTestUsingParameters',['firstNum'=>4,'secondNum'=>4]);
$this->assertEquals(10,$calcu->getContent());
}
}
I have read the documentation,but i did't get the idea, how to do this.?
Anyone know about this problem?

Related

assertResponseRedirects method with PHPUnit by passing the URI as a parameter

Can someone explain to me why when I use the assertResponseRedirects method with PHPUnit by passing the URI as a parameter:
class UserControllerTest extends WebTestCase
{
public function testUnauthenticatedIsRedirected(): void
{
$this->client->request('GET', '/account');
static::assertResponseRedirects('/login');
}
}
I have this error:
Failed asserting that Symfony\Component\HttpFoundation\RedirectResponse Object &0000000044abc158000000000cda95f8 (
'targetUrl' => 'http://localhost/login'
...
But if I put the absolute URL, the test works:
public function testUnauthenticatedIsRedirected(): void
{
$this->client->request('GET', '/account');
static::assertResponseRedirects('http://localhost/login');
}
Everyone puts the URI and it works, but not me... I'm on Symfony 5.2.1
Thank you in advance
$this->client->request('GET', '/account');
$response = $this->client->getResponse();
$this->assertEquals(Response::HTTP_FOUND, $response->getStatusCode());
$location = $response->headers->get('location');
$this->assertEquals('expected URL here', $location);

How to inject dependency using Factory Pattern in Symfony2

I have this situation
abstract class Importer {
const NW = 1;
public static function getInstance($type)
{
switch($type)
{
case(self::NW):
return new NWImporter();
break;
}
}
protected function saveObject(myObject $myObject)
{
//here I need to use doctrine to save on mongodb
}
abstract function import($nid);
}
and
class NWImporter extends Importer
{
public function import($nid)
{
//do some staff, create myObject and call the parent method to save it
parent::saveObject($myObject);
}
}
and I want to use them like this
$importer = Importer::getInstance(Importer::NW);
$importer->import($nid);
my question is: how to inject doctrine to be used in saveObject method?
thanks
You need to configure your importer as a symfony service :
services:
test.common.exporter:
# put the name space of your class
class: Test\CommonBundle\NWImporter
arguments: [ "#doctrine" ]
then in NWImporter define a constructor with a parameter that will have the doctrine instance
public function __construct($doctrine)
{
$this->doctrine= $doctrine;
}
with this solution you can avoid using a factory method as symfony does it for you but if you wanna to keep it, When you call $importer = Importer::getInstance(Importer::NW); from your controller you can inject the doctrine argument in your factory method :
abstract class Importer {
const NW = 1;
public static function getInstance($type, $doctrine)
{
switch($type)
{
case(self::NW):
return new NWImporter($doctrine);
break;
}
}
protected function saveObject(myObject $myObject)
{
//here I need to use doctrine to save on mongodb
}
abstract function import($nid);
}
then in your controller you should to do something like that :
$doctrine = $this->container->get('doctrine');
$importer = Importer::getInstance(Importer::NW, $doctrine);
$importer->import($nid);

How can I bind a Symfony config tree to an object

How would I go about binding a Symfony config tree to a class rather than returning an array?
Using Symfony\Component\Config\Definition\Processor returns an array.
In my case I want the config to be bound to a class so I can use methods to combine parts of the data.
Here is a simple example of my use case. I want the config bound to a class so I can use a method to join table.name and table.version together (my actual use case is more complex, but this is a simple example)
config.yml
db:
table:
name: some_table
version: v2
ConfigurationInterface
class DBConfiguration implements ConfigurationInterface
{
/**
* {#inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('db');
$rootNode
->children()
->arrayNode('table')
->children()
->scalarNode('name')->isRequired()->end()
->scalarNode('version')->end()
->end()
->end()
;
return $treeBuilder;
}
}
Class I want to bind the config to
class DB
{
public $table;
public function __construct()
{
$this->table = new Table();
}
}
class Table
{
public $name;
public $version;
/**
* #return string
* Calculate the full table name.
*/
public function getTableName()
{
return $this->name.'-'.$this->version;
}
}
The Symfony Config component doesn't support that.
However, in a Symfony project, this is usually done at the container compile phase. In your bundle's Extension class, you will have access to the configuration tree of your bundle in array form.
You can then take this array and assign it to a service defined in the service container that will create your config object.
This is exactly how DoctrineBundle's configuration class is built:
Abstract services (for the configuration and the factory) are defined in dbal.xml
When loading DoctrineBundle's extension, an instance of the abstract config service is created for each defined connection.
An instance of the abstract factory service is created for each defined connection.
The options array is then passed to the abstract factory service along with the configuration
When creating an instance, the factory then does the necessary transformations.
As far as I know, Symfony has no native support for this, however, you could implement it yourself. You could use subset of Symfony Serializer Component in charge of deserialization, but I think it would be an overkill. Especially since I don't see any PublicPropertyDenormalizer, only GetSetMethodNormalizer (which is denormalizer too). Therefor you would have to either make your config objects have get/set methods or roll PublicPropertyDenormalizer on your own. Possible but it really seems like an overkill and doesn't look like helping much:
Symfony Serializer Component
$array = [
'field1' => 'F1',
'subobject' => [
'subfield1' => 'SF1',
],
];
class MyConfigObject implements Symfony\Component\Serializer\Normalizer\DenormalizableInterface
{
private $field1;
private $subobject;
public function getField1()
{
return $this->field1;
}
public function setField1($field1)
{
$this->field1 = $field1;
}
public function getSubobject()
{
return $this->subobject;
}
public function setSubobject(SubObject $subobject)
{
$this->subobject = $subobject;
}
public function denormalize(\Symfony\Component\Serializer\Normalizer\DenormalizerInterface $denormalizer, $data, $format = null, array $context = array())
{
$obj = new static();
$obj->setField1($data['field1']);
$obj->setSubobject($denormalizer->denormalize($data['subobject'], 'SubObject'));
return $obj;
}
}
class SubObject
{
private $subfield1;
public function getSubfield1()
{
return $this->subfield1;
}
public function setSubfield1($subfield1)
{
$this->subfield1 = $subfield1;
}
}
$normalizer = new \Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer();
$obj = (new MyConfigObject())->denormalize($normalizer, $array);
Native PHP Way
Imo this is a lot easier than above as Symfony Serializer wasn't really ment for that.
$array = [
'field1' => 'F1',
'subobject' => [
'subfield1' => 'SF1',
],
];
trait Denormalizable
{
public function fromArray($array)
{
foreach ($array as $property => $value) {
if (is_array($value)) {
if ($this->$property instanceof ArrayDenormalizableInterface) {
$this->$property->fromArray($value);
} else {
$this->$property = $value;
}
} else {
$this->$property = $value;
}
}
}
}
interface ArrayDenormalizableInterface
{
public function fromArray($array);
}
class MyConfigObject implements ArrayDenormalizableInterface
{
use Denormalizable;
public $field1;
public $subobject;
public function __construct()
{
$this->subobject = new SubObject();
}
}
class SubObject implements ArrayDenormalizableInterface
{
use Denormalizable;
public $subfield1;
}
$myConf = new MyConfigObject();
$myConf->fromArray($array);
Whatever way you choose, you can now just take array returned from symfony processor and turn it into a config object you need.

Mocking Illuminate\Database\Eloquent\Model

I need to mock Laravel's Eloquent\Model with Mockery and it is kind of tricky because it uses static methods.
I solved this issue with the following code but I wonder if there is a better/smarter way to do this.
<?php
use Ekrembk\Repositories\EloquentPostRepository;
class EloquentPostRepositoryTest extends TestCase {
public function __construct()
{
$this->mockEloquent = Mockery::mock('alias:Ekrembk\Post');
}
public function tearDown()
{
Mockery::close();
}
public function testTumuMethoduEloquenttenAldigiCollectioniDonduruyor()
{
$eloquentReturn = 'fake return';
$this->mockEloquent->shouldReceive('all')
->once()
->andReturn($eloquentDongu);
$repo = new EloquentPostRepository($this->mockEloquent);
$allPosts = $repo->all();
$this->assertEquals($eloquentReturn, $allPosts);
}
}
Tough to tell without the source of "Ekrembk\Repositories\EloquentPostRepository", but, I see a couple of issues. It looks like within your EloquentPostRepository, you're calling a static. You shouldn't do that. It makes it hard to test (as you've discovered). Assuming that Ekrembk\Post extends from Eloquent, you can do this instead:
<?php
namespace Ekrembk\Repositories
class EloquentPostRepository {
protected $model;
public __construct(\Ekrembk\Post $model) {
$this->model = $model;
}
public function all()
{
$query = $this->model->newQuery();
$results = $query->get();
return $results;
}
}
Then, your test will be simpler:
<?php
use Ekrembk\Repositories\EloquentPostRepository;
class EloquentPostRepositoryTest extends TestCase {
public function tearDown()
{
Mockery::close();
}
public function testTumuMethoduEloquenttenAldigiCollectioniDonduruyor()
{
$mockModel = Mockery::mock('\Ekrembk\Post');
$repo = new EloquentPostRepository($mockModel);
$eloquentReturn = 'fake return';
$mockModel->shouldReceive('newQuery')->once()->andReturn($mockQuery = m::mock(' \Illuminate\Database\Eloquent\Builder'));
$result = $mockQuery->shouldReceive('get')->once()->andReeturn($eloquentReturn);
$this->assertEquals($eloquentReturn, $result);
}
}
Didn't test the above so it might have issues, but you should get the idea.
If you look in Illuminate\Database\Eloquent\Model, you'll see that "public static function all" is really just calling "get" on an instantiated eloquent model.

Test methods of Abstract Class with PHPUnit

I have an abstract class that has common methods in it, that I wish to test, so I do not have to keep testing them in each class that extends this class.
abstract class Class1 implements iClass1
{
const VALUE = 'A';
private $Return;
public function __construct($Field = NULL)
{
if( ! is_null($Field) )
$this->SetField($Field);
}
public function GetField()
{
return $this->Return;
}
public function SetField($Field)
{
if (strlen($Field) != 3)
throw new CLASS1_EXCEPTION('Field "' . $Field . '" must be 3 digits.');
$this->Return = $FieldCode;
}
abstract function CalculateData();
}
I want to create the basic test case then that will test the constructor, and the GetField and other functions, then my other test files can test the abstract functions.
I want to be able to test the const has not changed, the field throws the exception etc...
TEST:
class TEST_CLASS1 extends PHPUnit_Framework_TestCase
{
protected function setUp()
{
require_once('CLASS1.php');
}
public function testConstants()
{
$this->assertEquals(CLASS1, 'A');
}
/* #expectedException CLASS1_EXCEPTION
public function testLargeFieldException()
{
$class1 = new CLASS1('ABCD');
$class1 = new CLASS1();
$class1->SetField('ABCD');
}
}
How do I create the tests since I can not create the CLASS1 object as it is an abstract class?
One option is to create a
TestableClass1 extends Class1 {
public function CalculateData() {}
}
and use that class for your tests.
The other option is to do pretty much the same but use an API phpunit provides you with:
For this see the sample Example 10.13: Testing the concrete methods of an abstract class of the phpunit documentation:
A simpler example:
abstract class AbstractClass
{
public function concreteMethod()
{
return 5;
}
public abstract function abstractMethod();
}
class AbstractClassTest extends PHPUnit_Framework_TestCase
{
public function testConcreteMethod()
{
$sut = $this->getMockForAbstractClass('AbstractClass');
$this->assertSame(5, $sut->concreteMethod());
}
}

Resources