Phpunit method #depends not receiving - unit-testing

Can somebody explain me why the method 'testGetUniqueUser' is receiving nothing as argument from the method it depends ? or how can I pass it an argument coming from another method ? All I'm trying to accomplish is as soon a user is created, I do a GET request to verify if this one exist.
/**
* #depends ::testPostUser201
* #param int $id
*/
public function testGetUniqueUser(int $id)
{
self::$client->request(
request::METHOD_GET,
UserController::USER_API_PATH . "/" . $id
);
/** #var Response $response */
$response = self::$client->getResponse();
self::assertEquals(
Response::HTTP_OK, $response->getStatusCode()
);
$dataResponse = json_decode($response->getContent(), true);
self::assertArrayHasKey('user', $dataResponse);
}
/**
* #covers ::postUser
* #return int
*/
public function testPostUser201(): int
{
$data = [
'username' => 'ener',
'email' => 'dgor#live.com',
'password' => 'memories',
'enable' => 'true'
];
self::$client->request(
Request::METHOD_POST,
UserController::USER_API_PATH,
[], [], [], json_encode($data)
);
/** #var Response $response */
$response = self::$client->getResponse();
self::assertEquals(
Response::HTTP_CREATED,
$response->getStatusCode()
);
$dataResponse = json_decode($response->getContent(), true);
$id = $dataResponse['id'];
self::assertArrayHasKey('user', $dataResponse);
return $id;
}

Related

upload not running with VichUploaderBundle

I would like to use a VichUploaderBundle for upload files in my symfony 3.2.3 project (PHP 5.6). I try lot of thing but nothing upload run. But the persistance layer run perfeclty with my database.
config.yml
knp_gaufrette:
stream_wrapper: ~
adapters:
fileupload_adapter:
local:
directory: %kernel.root_dir%/../web/
create: true
filesystems:
fileupload_fs:
adapter: fileupload_adapter
# VichUploaderBundle Configuration
vich_uploader:
db_driver: orm
twig: true
storage: gaufrette
mappings:
tgmedia_file:
uri_prefix: web
upload_destination: fileupload_fs
namer: vich_uploader.namer_origname
Entity
namespace MediaBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use TweedeGolf\MediaBundle\Model\AbstractFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ORM\Entity
* #Vich\Uploadable
* #ORM\HasLifecycleCallbacks
* #ORM\Table
*/
class FileUpload
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="tgmedia_file", fileNameProperty="imageName")
*
* #var File
*/
protected $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $imageName;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
protected $updatedAt;
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #return File|null
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*
* #return Product
*/
public function setImageFile(File $image = null)
{
$this->imageFile = $image;
if ($image) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
return $this;
}
/**
* #param string $imageName
*
* #return FileUpload
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* #return string|null
*/
public function getImageName()
{
return $this->imageName;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return FileUpload
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
}
The formType
<?php
namespace MediaBundle\Form;
use MediaBundle\Entity\File;
use MediaBundle\Entity\FileUpload;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Vich\UploaderBundle\Form\Type\VichFileType;
use Vich\UploaderBundle\Form\Type\VichImageType;
class FileUploadType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('imageName')
->add('imageFile', VichImageType::class, [
'required' => false,
'allow_delete' => true,
'download_link' => true,
'mapped' => false,
'data_class' => null
])
->add('submit', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => FileUpload::class,
'csrf_protection' => false,
));
}
}
Controller
<?php
namespace MediaBundle\Controller;
use MediaBundle\Entity\File;
use MediaBundle\Entity\FileUpload;
use MediaBundle\Entity\Product;
use MediaBundle\Form\FileType;
use MediaBundle\Form\FileUploadType;
use MediaBundle\Form\ProductType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class MainController extends Controller
{
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$fileUploaded = new FileUpload();
$form = $this->createForm(FileUploadType::class, $fileUploaded, array(
'action' => $this->generateUrl('media_main')
));
$form->handleRequest($request);
if ($form->isSubmitted())
{
$fileUploaded->setUpdatedAt(new \DateTime());
$fileUploaded->setImageFile($form->get('imageFile')->getData());
$em->persist($fileUploaded);
$em->flush();
}
return $this->render('MediaBundle:main:index.html.twig', array(
'form' => $form->createView()
));
}
}
Where is my error ? What wrong ?
uri_prefix: /project/web/fileupload_fs
upload_destination: '%kernel.root_dir%/../web/fileupload_fs'
uri_prefix begins from www folder.
and change controller like that
if ($form->isSubmitted() && $form->isValid())
{
$em->persist($fileUploaded);
$em->flush();
}

Symfony 3: UniqueEntity(errorPath) not working

I have an entity called ClassSubject and you can see it bellow,
/**
* ClassSubject
*
* #ORM\Table(name="class_subject")
* #ORM\Entity(repositoryClass="PIE10Bundle\Repository\ClassSubjectRepository")
*
* #UniqueEntity( fields={"class", "subjects"},
* errorPath="subjects",
* message="This subject is already added"
* )
*/
class ClassSubject
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var int
*
* #ORM\ManyToOne(targetEntity="Classes")
* #ORM\JoinColumn(name="class_id", referencedColumnName="id")
*/
private $class;
/**
* #var int
*
* #ORM\ManyToOne(targetEntity="Subject")
* #ORM\JoinColumn(name="subject_id", referencedColumnName="id")
*/
private $subjects;
as you can see, I want to make this Unique Entity so I am following this guide.
Further I have added the followings to the top of the entity file,
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
After all when I submit data it still adds duplicating rows to the table. For an example,
if the table exists with a row like, class=clsA and subjects=subA and if I try to insert with same values, it inserts data with no validation/message "This subject is already added"
My controller is like below,
public function addTeacherSubjectAction( $id, Request $request )
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('PIE10Bundle:Users')->find($id);
$subjects = $em->getRepository('PIE10Bundle:Subject')->findAll();
$form = $this->createForm(ClassSubjectType::class,$subjects);
$form->handleRequest($request);
if( $form->isSubmitted() && $form->isValid() )
{
$allSubjects = $form['subject']->getData();
foreach( $allSubjects as $subject )
{
$subject_repo = $em->getRepository('PIE10Bundle:Subject')->find($subject->getId());
$teacherSubject = new TeacherSubjects();
$teacherSubject->setTeachers($user);
$teacherSubject->setSubjects($subject_repo);
$em->persist($teacherSubject);
$em->flush();
}
$this->addFlash('notice',
'Subjects added');
return $this->redirectToRoute('user_teachers');
}
return $this->render( 'PIE10Bundle:Form:layout_commom_form.html.twig',
array( 'title' => 'Add Subjects',
'form' => $form->createView() )
);
}
and the ClassSubjectType is like below,
class ClassSubjectType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('subject',
EntityType::class,
array('class' => 'PIE10Bundle:Subject',
'expanded' => true,
'multiple' => true,
'attr' => array( 'class' => 'form-control',
'style' => 'margin:5px 0;')));
$builder->add('Add Classes',
SubmitType::class,
array('attr' => array('class' => 'btn btn-primary',
'style' => 'margin:15px 0;')) );
}
}
So I need to know what is wrong with my code. Thanks in advance.

Zend Framework 2 Doctrine 2 many to many entity relation issue

I have the following tables: films, categories, films_categories and the entities:
Film.php
<?php
namespace Admin\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="films")
*/
class Film{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
* #ORM\Column(length=11)
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
/* .... */
/**
* #ORM\ManyToMany(targetEntity="Category")
* #ORM\JoinTable(name="films_categories",
* joinColumns={#ORM\JoinColumn(name="film_id", referencedColumnName = "id")},
* inverseJoinColumns={#ORM\JoinColumn(name="category_id", referencedColumnName="id")})
*/
private $categories;
public function __construct(){
$this->categories = new ArrayCollection();
}
public function getCategoriesNames(){
$names = array();
foreach($this->categories as $category){
$names[] = $category->getName();
}
return $names;
}
public function getId(){
return $this->id;
}
public function setId($id){
$this->id = $id;
}
/* ... */
/**
* #return Collection
*/
public function getCategories(){
return $this->categories;
}
public function addCategories(Collection $categories){
foreach($categories as $category){
$this->categories->add($category);
}
}
public function removeCategories(Collection $categories){
foreach($categories as $category){
$this->categories->removeElement($category);
}
}
}
Category.php
<?php
namespace Admin\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="categories")
*/
class Category {
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/* ... */
public function getId(){
return $this->id;
}
public function setId($id){
$this->id = $id;
}
/* ... */
}
What I want to do is create a form and the action to add a new film and assign a category to it. Here is the form I used:
FilmFieldset.php
<?php
namespace Admin\Form;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
use DoctrineORMModule\Stdlib\Hydrator\DoctrineEntity;
use Admin\Entity\Film;
class FilmFieldset extends Fieldset implements InputFilterProviderInterface{
protected $entityManager;
public function __construct($em){
parent::__construct('film');
$this->entityManager= $em;
$this->setHydrator(new DoctrineEntity($em,'Admin\Entity\Film'))
->setObject(new Film());
#$this->setAttribute('method','post');
#$this->setAttribute('class','standardForm');
$this->add(array(
'name' => 'id',
'type' => 'hidden'
));
/* ... */
$this->add(
array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'categories',
'attributes' => array(
'multiple' => 'multiple',
),
'options' => array(
'object_manager' => $em,
'target_class' => 'Admin\Entity\Category',
'property' => 'name',
'label' => 'Categories: ',
'disable_inarray_validator' => true
),
)
);
}
public function getInputFilterSpecification(){
return array(
/* .... */
'categories' => array(
'required' => true,
),
);
}
}
The FilmForm.php
<?php
namespace Admin\Form;
use Zend\Form\Form;
use Zend\Stdlib\Hydrator\ClassMethods;
use Admin\Entity\Film;
use Zend\InputFilter\InputFilter;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
class FilmForm extends Form{
public function __construct($em){
parent::__construct('filmForm');
$this->setAttribute('method','post')
->setAttribute('class','standardForm')
->setHydrator(new DoctrineHydrator($em,'\Admin\Entity\Film'))
->setInputFilter(new InputFilter());
/* I register the fieldset through a service and not directly here */
// $this->add(array(
// 'type' => new FilmFieldset($em),
// 'options' => array(
// 'user_as_base_fieldset' => true
// )
// ));
$this->add(array(
'name' => 'security',
'type' => 'Zend\Form\Element\Csrf'
));
$this->add(array(
'name' => 'submit',
'type' => 'submit',
));
$this->setValidationGroup(array(
'security',
'film' => array(
'categories',
)
));
}
}
The addAction:
public function addAction() {
$em = $this->getEntityManager();
$form = $this->getForm();
$film = new Film();
$form->bind($film);
if($request->isPost()){
$post = array_merge_recursive(
$request->getPost()->toArray(),
$request->getFiles()->toArray()
);
$form->setData($post);
if($form->isValid()){
$categories = array();
foreach($post['film']['categories'] as $categoryId){
$categories[] = $em->getRepository('Admin\Entity\Category')->find($categoryId);
}
$film->addCategories($categories);
$em->persist($film);
$em->flush();
}else{
// the form is not valid
}
}
The result is various errors and and ORMExcption with the message "Found entity of type on association Admin\Entity\Film#categories, but expecting Admin\Entity\Category"
Please help me out, I'm literally freaking out over this! Thank you :)
From what i found out from this is some thing like this that your entity is receiving Admin\Entity\Film#categories and in this part categories is some what a value. Where as your entity is expecting an object of type Admin\Entity\Film#categories.
To get over this you have to create a
public function SetCategory(Admin\Entity\Category Category)
{
$this->categories(or category or w/e your variable name is)= Category;
}
public function getCategory()
{
return $this->categories(or category or w/e your variable name is);
}
And then in your Action you have to pass object of Category to Film Entity in some thing like this
$Film->SetCategory($categoryObj);
Of course you have to set your business logic according to your part, but this error Should be removed by this apporach.
You need to define the FQCN for the targetEntity.
Change:
* #ORM\ManyToMany(targetEntity="Category")
to:
* #ORM\ManyToMany(targetEntity="Admin\Entity\Category")
This has to do with hydration and lazy loading. I'm no expert on this, but the #categories is a proxy object, and when you are going to save it, it's complaining because it needs to be an actual collection, not a proxy object to a collection.
If you did noobie-php's approach, you're re-attaching new category objects on the main object, so they're not proxies any more.
This is frustrating, as Doctrine was supposed to save a lot of the hassle of this, but it doesn't actually do what you'd naturally expect in many situations. I'd found a bug ticket on this some time ago but can't find it now - will add it to this if I can find it.

Using Zend Framework 2 + Doctrine2.3 with ObjectSelect and ManyToOne relations

I"m having a bit of trouble with using Doctrine's ObjectSelect on ManyToOne relations.
The relations I have below using ManyToMany work 100% adding and editing. My edit form is populated with the current selection without any problems.
The issue arises with the ManyToOne relations, it appears the form is not being populated with the current selection.
I have tried dumping the Task entity before I bind it to the form and it looks 100% right, all my relations are populated in the entity.
However after binding it, the form is being displayed without the current value selected.
Task entity:
/**
* #ORM\Entity
* #ORM\Table(name="tasks")
*/
class Task
{
/**
* #ORM\Id
* #ORM\Column(type="integer");
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
...
/**
* #ORM\ManyToOne(targetEntity="Category")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
...
/**
* #ORM\ManyToMany(targetEntity="ZDUser\Entity\User")
* #ORM\JoinTable(name="tasks_assigned_user_linker",
* joinColumns={#ORM\JoinColumn(name="task_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
protected $assignedUsers;
/**
* Initialize
*/
public function __construct()
{
$this->assignedUsers = new ArrayCollection();
}
/**
* We need a few getters and setters
*/
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
public function getCategory() {
return $this->category;
}
public function setCategory(Category $category) {
$this->category = $category;
}
public function getAssignedUsers() {
return $this->assignedUsers;
}
public function addAssignedUsers(Collection $users) {
foreach ($users as $user) {
$this->assignedUsers->add($user);
}
}
public function removeAssignedUsers(Collection $users) {
foreach ($users as $user) {
$this->assignedUsers->removeElement($user);
}
}
}
I'm using ManyToOne in most of my entities, I find this way a little easier and extensible going forward. I can just add addtional entities and link them to other ones without having to do relations on both sides.
Category Entity
/**
* #ORM\Entity
* #ORM\Table(name="task_categories")
* #property int $id
* #property string $name
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer");
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", nullable=false)
*/
protected $name;
...
/**
* Setters and getters we need
*/
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = (int) $id;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
}
User Entity:
/**
* #ORM\Entity
* #ORM\Table(name="users")
*/
class User implements UserInterface, ProviderInterface
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
...
/**
* #ORM\ManyToMany(targetEntity="ZDUser\Entity\Group")
* #ORM\JoinTable(name="users_groups_linker",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* Initialies the object
*/
public function __construct()
{
$this->groups = new ArrayCollection();
}
/* Getters and setters, we must define these for the implementation to work */
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = (int) $id;
}
/* Get and add groups */
public function getGroups()
{
return $this->groups;
}
public function addGroup(Group $group)
{
$this->groups->add($group);
}
Form code:
class TaskForm extends Form implements ObjectManagerAwareInterface
{
protected $objectmanager;
public function __construct(EntityManager $em)
{
// we want to ignore the name passed
parent::__construct('task');
$this->setHydrator(new DoctrineHydrator($em,'TaskList\Entity\Task'));
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'id',
'attributes' => array(
'type' => 'hidden',
),
));
$this->add(array(
'name' => 'subject',
'type' => 'Text',
'options' => array(
'label' => 'Subject',
),
));
$this->add(array(
'name' => 'category',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => array(
'label' => "Category",
'object_manager' => $em,
'target_class' => 'TaskList\Entity\Category',
'property' => 'name',
),
));
$this->add(array(
'name' => 'assignedUsers',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'attributes' => array(
'multiple' => 'multiple',
),
'options' => array(
'label' => "Assigned To (User)",
'object_manager' => $em,
'target_class' => 'ZDUser\Entity\User',
'property' => 'email',
),
));
Controller for Edit & Add:
public function addAction()
{
$this->addedit();
// Grab form
$form = new TaskForm($this->getEntityManager());
// Grab any request we may have
$request = $this->getRequest();
// If it a post ...
if ($request->isPost()) {
$task = new Task();
$form->bind($task);
// Populate data
$form->setData($request->getPost());
// Check if the form is valid
if ($form->isValid()) {
// Setup some things we need
$task->setCreated(new \DateTime("now"));
// Save
$this->getEntityManager()->persist($task);
$this->getEntityManager()->flush();
// Redirect to list of tasks
return $this->redirect()->toRoute('tasklist');
}
}
return array(
'form' => $form
);
}
public function editAction()
{
$this->addedit();
// Get ID or redirect
$id = (int)$this->getEvent()->getRouteMatch()->getParam('id');
if (!$id) {
return $this->redirect()->toRoute('tasklist');
}
// Create a form
$form = new TaskForm($this->getEntityManager());
// Grab entity from doctrine
$task = $this->getEntityManager()->find('TaskList\Entity\Task', $id);
// Bind the form to the task
$form->bind($task);
// Check if we have a request and if its POST
$request = $this->getRequest();
if ($request->isPost()) {
// If it is, set the form data from the request
$form->setData($request->getPost());
// If the form is valid, bind the values
if ($form->isValid()) {
// Setup some things we need
$task->setLastUpdated(new \DateTime("now"));
// Flush the update
$this->getEntityManager()->flush();
// Redirect to list of tasks
return $this->redirect()->toRoute('tasklist');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
I'm so sure I'm missing something really simple.
I had a similar problem, see this issue on the DoctrineORMModule GitHub for more info.
It's something to do with Doctrine not returning the correct ID field from metadata when Proxies Entities are loaded. The solutions are as follows:
Wait for official fix in Doctrine 2.4 (you can install 2.4-beta2 now!).
Subclass the ObjectSelect to force the use of the correct ID field (someone in the aforelinked issue did this).
Patch DoctrineModule with this:
--- doctrine/doctrine-module/src/DoctrineModule/Form/Element/Proxy.php 2013-03-11 17:49:55.406011600 -0300
+++ doctrine/doctrine-module/src/DoctrineModule/Form/Element/Proxy.php 2013-03-11 17:51:33.592710900 -0300
## -240,7 +240,10 ##
if (count($identifier) > 1) {
//$value = $key;
} else {
- $value = current($metadata->getIdentifierValues($value));
+ // Doctrine has a bug that makes the following not work,
+ // this is a horrible workaround until Doctrine 2.4 is released with a fix.
+ //$value = current($metadata->getIdentifierValues($value));
+ $value = $value->getId();
}
}
}
The $value->getId() relies on that method being available in the corresponding entity. This isn't recommended but a quick fix.
Probably not the right way? I posted my idea to their ML :)
Probably not the right way? I posted my idea to their ML :)
diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
index cba525a..2f62375 100644
--- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
+++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
## -667,7 +667,17 ## class ClassMetadataInfo implements ClassMetadata
return $id;
}
- $value = $this->reflFields[$this->identifier[0]]->getValue($entity);
+
+ /**
+ * NK: First try use the getter, in the case of a proxied object, the reflection is not going to work
+ * as the proxied object does not have any properties
+ */
+ $getter = 'get' . ucfirst($this->identifier[0]);
+ if (method_exists($entity, $getter)) {
+ $value = $entity->$getter();
+ } else {
+ $value = $this->reflFields[$this->identifier[0]]->getValue($entity);
+ }

Symfony2 - Tests with FOSUserBundle

i would write a test for Symfony2 with FOSUserBundle.
At the moment i tried some ways and no one works.
I need a function like "createAuthClient".
Here is my basic class.
I post it because you could understand my problem better.
<?php
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\BrowserKit\Cookie;
class WebTestMain extends WebTestCase
{
protected static $container;
static protected function createClient(array $options = array(), array $server = array())
{
$client = parent::createClient($options, $server);
self::$container = self::$kernel->getContainer();
return $client;
}
static function createAuthClient(array $options = array(), array $server = array())
{
// see lines below with my tries
}
}
First try:
if(static::$kernel === null)
{
static::$kernel = static::createKernel($options);
static::$kernel->boot();
}
if(static::$container === null)
{
self::$container = self::$kernel->getContainer();
}
$parameters = self::$container->getParameter('test');
$server = array_merge(array('HTTP_HOST' => $parameters['host'], 'HTTP_USER_AGENT' => $parameters['useragent']), $server);
$client = self::createClient($options, $server);
$userProvider = self::$container->get('fos_user.user_manager');
$user = $userProvider->findUserBy(array('id' => 1));
$client->getCookieJar()->set(new Cookie('MOCKSESSID', true));
$session = self::$kernel->getContainer()->get('session');
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$client->getContainer()->get('security.context')->setToken($token);
$session->set('_security_main', serialize($token));
return $client;
Then i searched and searched...
My second try.
if(static::$kernel === null)
{
static::$kernel = static::createKernel($options);
static::$kernel->boot();
}
if(static::$container === null)
{
self::$container = self::$kernel->getContainer();
}
$parameters = self::$container->getParameter('test');
$server = array_merge(
array(
'HTTP_HOST' => $parameters['host'],
'HTTP_USER_AGENT' => $parameters['useragent'],
'PHP_AUTH_USER' => 'admin',
'PHP_AUTH_PW' => 'admin'
),
$server
);
$client = static::createClient(array(), array());
$client->followRedirects();
return $client;
And here is my last try before i post this question...
$client = self::createClient($options, $server);
$parameters = self::$container->getParameter('test');
$server = array_merge(
array(
'HTTP_HOST' => $parameters['host'],
'HTTP_USER_AGENT' => $parameters['useragent']
),
$server
);
$client->setServerParameters($server);
$usermanager = self::$container->get('fos_user.user_manager');
$testuser = $usermanager->createUser();
$testuser->setUsername('test');
$testuser->setEmail('test#mail.org');
$testuser->setPlainPassword('test');
$usermanager->updateUser($testuser);
return $client;
Thank you in Advance.
The best way I have found to test with an authenticated user is to just visit your login page and submit the form with user name and password you have loaded from a fixture. This may seem slow and cumbersome but will test what the user will actually do. You can even create your own method to make using it quick and easy.
public function doLogin($username, $password) {
$crawler = $this->client->request('GET', '/login');
$form = $crawler->selectButton('_submit')->form(array(
'_username' => $username,
'_password' => $password,
));
$this->client->submit($form);
$this->assertTrue($this->client->getResponse()->isRedirect());
$crawler = $this->client->followRedirect();
}
Create an AbstractControllerTest and create an authorized client on setUp() as follow:
<?php
// ...
use Symfony\Component\BrowserKit\Cookie;
abstract class AbstractControllerTest extends WebTestCase
{
/**
* #var Client
*/
protected $client = null;
public function setUp()
{
$this->client = $this->createAuthorizedClient();
}
/**
* #return Client
*/
protected function createAuthorizedClient()
{
$client = static::createClient();
$container = $client->getContainer();
$session = $container->get('session');
/** #var $userManager \FOS\UserBundle\Doctrine\UserManager */
$userManager = $container->get('fos_user.user_manager');
/** #var $loginManager \FOS\UserBundle\Security\LoginManager */
$loginManager = $container->get('fos_user.security.login_manager');
$firewallName = $container->getParameter('fos_user.firewall_name');
$user = $userManager->findUserBy(array('username' => 'REPLACE_WITH_YOUR_TEST_USERNAME'));
$loginManager->loginUser($firewallName, $user);
// save the login token into the session and put it in a cookie
$container->get('session')->set('_security_' . $firewallName,
serialize($container->get('security.context')->getToken()));
$container->get('session')->save();
$client->getCookieJar()->set(new Cookie($session->getName(), $session->getId()));
return $client;
}
}
NOTE: Please, replace the username with your test username.
Then, extends the AbstractControllerTest and use the global $client to make requests as follow:
class ControllerTest extends AbstractControllerTest
{
public function testIndexAction()
{
$crawler = $this->client->request('GET', '/admin/');
$this->assertEquals(
Response::HTTP_OK,
$this->client->getResponse()->getStatusCode()
);
}
}
This method tested and works fine