lundi 8 juin 2015

PHPUnit: How to set a mocked method to return different values depending on the passed value

I have a class that, passed some Doctrine entities, from them retrieves data for other Doctrine entities and using their values make some calculations.

I pass all the needed entites and the Doctrine EntityManager through the constructor that has this signature:

public function __construct(array $entities, $em)

Now, reading the Symfony's documentation about the testing of code that interacts with databases I read that I can mock both the $entities variable and the EntityManager.

To mock the EntityManager i can use something like (from the linked page of the Symfony's documentation):

// Last, mock the EntityManager to return the mock of the repository
$entityManager = $this
    ->getMockBuilder('\Doctrine\Common\Persistence\ObjectManager')
    ->disableOriginalConstructor()
    ->getMock();
$entityManager->expects($this->once())
    ->method('getRepository')
    ->will($this->returnValue($employeeRepository));

As you can see, the documentation suggests to mock the method getRepository() and set it to return the before mocked entity (not reported in the sample code above).

My problem is that i call getRepository more than one time in the class and each time it has to return different entities, based on the real value passed. For example i need it in ways similar to the ones below:

// $order is a Doctrine entity

/** @var  $customer \AppBundle\Entity\Customer */
$customer = $order->getPlacedBy()->getProfile()->getUsername();

// Get product information
$purchases = $this->em->getRepository('AppBundle:Purchase')->findBy(
     array('inOrder' => $order)
);

...

// ... Get "other data" (this is a dummy name for the sake of the example.
// In the reality those are real Doctrine entities)
/** @var  $otherData \AppBundle\Entity\OtherData */
$otherData = $this->em->getRepository('AppBundle:OtherData')->findBy(
     array('forOrder' => $order)
);

As you can see i call the same method more than one time and each time i call it to get something different from the previous call. In the sample code above, I use it 2 times: one to get the Purchase Entity and one to get the OtherData entity (it's a dummy name, not a real entity. It is used just for the sake of the example).

Is there a way to mock an object, and specifically the getRepository method, in a way it returns different values depending on what i pass, or have I to use directly a database?

Aucun commentaire:

Enregistrer un commentaire