Search code examples
phpsymfonyphpunitsymfony-3.4

PHPUnit & Doctine : How to mock my entities?


I'm creating a library with Symfony3.4. And I'm making my tests with PHPUnit.

I've got a method which retrives data from my DB, I have 2 entities which are in a relation, Collection() and CollectionElement() :

public function recording()
    {
        try {
            // [...]

            $collection = new Collection();
            $collection->setNomCollection($dbname);

            $collectionExists = $this->em->getRepository(Collection::class)
                ->findOneBy(['nomCollection' => $dbname]);

            // if user provided specific values for $file1, $file2, ... parameters.
            if ((empty($collectionExists)) and (count($datafile) > 0)) {
                // For now, assume USING/OPENING a database is to be done in READ ONLY MODE.
                $this->em->persist($collection);
                $this->em->flush();
            } else {
                $collection = $collectionExists;
            }

            // [....]

            $this->seqcount = count($temp_r);

            foreach($temp_r as $seqid => $line_r) {
                // Check if the file already exists
                $collectionElementExists = $this->em->getRepository(CollectionElement::class)
                    ->findOneBy(['fileName' => $line_r["filename"]]);

                if(empty($collectionElementExists)) {
                    $collectionElement = new CollectionElement();
                    $collectionElement->setIdElement($line_r["id_element"]);
                    $collectionElement->setCollection($collection);
                    $collectionElement->setFileName($line_r["filename"]);
                    $collectionElement->setSeqCount(count($temp_r));
                    $collectionElement->setLineNo($line_r["line_no"]);
                    $collectionElement->setDbFormat($line_r["dbformat"]);

                    $this->em->persist($collectionElement);
                    $this->em->flush();
                }
            }
        } catch (\Exception $e) {
            throw new \Exception($e);
        }
    }

Then I have to make some tests but I can't manage mocking my EntityManager :

    $collection = new Collection();
    $collection->setId(3);
    $collection->setNomCollection("db1");     
    $mockedEm = $this->createMock(EntityManager::class);

 $this->collectionMock = $this->getMockBuilder('AppBundle\Entity\IO\Collection')
            ->setMethods(['findOneBy'])
            ->getMock();
 $this->collectionMock->method("findOneBy")->will($this->returnValue($collection));

What can I do to make this work, please ? Furthermore, both entities calls findOneBy() ...

Thanks :)


Solution

  • You correctly mocked the manager with this.

    $mockedEm = $this->createMock(EntityManager::class);
    

    What you missed are the calls to getRepository.

    $repo = $this->createMock(EntityRepository::class);
    $mockedEm->expects($this->once())->method('getRepository')->with(CollectionElement::class)->willReturn($repo);
    

    After that you can have expectations for the findOneBy on the repository.

    $repo->expects($this->exactly(2))->method('findOneBy')
      ->withConsecutive(['fileName' => 'f1'], ['fileName' => 'f2'])
      ->willReturnOnConsecutiveCalls($entity1, $entity2);