Php 如何模拟';查找';symfony3中的方法

Php 如何模拟';查找';symfony3中的方法,php,symfony,testing,doctrine-orm,mocking,Php,Symfony,Testing,Doctrine Orm,Mocking,我试图模拟EntityRepository的find方法,这样测试就不会在数据库中查找数据,但似乎不起作用。下面是测试类的设置方法 public function setUp() { parent::setUp(); $this->client = static::createClient(); $this->peopleManager = $this->getMockBuilder(PeopleManager::class) ->

我试图模拟
EntityRepository
find
方法,这样测试就不会在数据库中查找数据,但似乎不起作用。下面是测试类的
设置
方法

public function setUp()
{
    parent::setUp();

    $this->client = static::createClient();
    $this->peopleManager = $this->getMockBuilder(PeopleManager::class)
        ->setMethods(['createPerson','peopleUpdate', 'peopleDelete', 'peopleRead'])
        ->disableOriginalConstructor()
        ->getMock();

   $this->repository = $this->getMockBuilder(EntityRepository::class)
       ->disableOriginalConstructor()
       ->getMock();

   $this->em = $this->getMockBuilder(EntityManager::class)
       ->disableOriginalConstructor()
       ->getMock(); 
}
这就是我们调用find函数的方法

public function updatePersonAction($id, Request $request)
{
    $repository = $this->getDoctrine()->getRepository('GeneralBundle:People');
    $person= $repository->find($id);
    if($person)
    {
        $data = $request->request->get('array');
        $createdPeople = array();
        $UpdatedPerson = "";
        foreach($data as $content)
        {
            $prueba = $this->get('people.manager');
            $UpdatedPerson = $prueba->peopleUpdate(
                $person,
                $content['name'],
                $content['surname'],
                $content['secondSurname'],
                $content['nationality'],
                $content['birthday'],
                $content['identityCard'],
                $content['identityCardType']
            );
            array_push($createdPeople, $person);
        }
        $serializedEntity = $this->get('serializer')->serialize($UpdatedPerson, 'json');
        return new Response($serializedEntity);
    } else {
        $serializedEntity = $this->get('serializer')->serialize('Doesn\'t exists any person with this id', 'json');
        return new Response($serializedEntity);
    }
}
调试器显示peoplemanager类是模拟的,但它不会模拟实体管理器和存储库


谢谢假设您要测试的类如下所示:

// src/AppBundle/Salary/SalaryCalculator.php
namespace AppBundle\Salary;

use Doctrine\Common\Persistence\ObjectManager;

class SalaryCalculator
{
    private $entityManager;

    public function __construct(ObjectManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function calculateTotalSalary($id)
    {
        $employeeRepository = $this->entityManager
            ->getRepository('AppBundle:Employee');
        $employee = $employeeRepository->find($id);

        return $employee->getSalary() + $employee->getBonus();
    }
}
由于ObjectManager通过构造函数注入到类中,因此很容易在测试中通过模拟对象:

// tests/AppBundle/Salary/SalaryCalculatorTest.php
namespace Tests\AppBundle\Salary;

use AppBundle\Entity\Employee;
use AppBundle\Salary\SalaryCalculator;
use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Persistence\ObjectManager;
use PHPUnit\Framework\TestCase;

class SalaryCalculatorTest extends TestCase
{
    public function testCalculateTotalSalary()
    {
        // First, mock the object to be used in the test
        $employee = $this->createMock(Employee::class);
        $employee->expects($this->once())
            ->method('getSalary')
            ->will($this->returnValue(1000));
        $employee->expects($this->once())
            ->method('getBonus')
            ->will($this->returnValue(1100));

        // Now, mock the repository so it returns the mock of the employee
        $employeeRepository = $this
            ->getMockBuilder(EntityRepository::class)
            ->disableOriginalConstructor()
            ->getMock();
        $employeeRepository->expects($this->once())
            ->method('find')
            ->will($this->returnValue($employee));

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

        $salaryCalculator = new SalaryCalculator($entityManager);
        $this->assertEquals(2100, $salaryCalculator->calculateTotalSalary(1));
    }
}
在本例中,您从内到外构建模拟,首先创建由存储库返回的employee,该employee本身由EntityManager返回。这样,测试中就不会涉及到真正的类

资料来源:

对于mocky来说,这是非常微不足道的,尝试一下类似于
$repo->shouldReceive('find')->once()->andReturn([1,2,3])谢谢,这是非常有用的!!