如何在Symfony 3中模拟'find'方法

时间:2017-04-25 15:02:15

标签: php symfony testing doctrine-orm mocking

我正在尝试模拟find的{​​{1}}方法,以便测试不会查找数据库中的数据,但它似乎不起作用。这是测试类的EntityRepository方法

setUp

这是我们调用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(); 
}

调试器显示人员管理器类被模拟,但它不模拟实体管理器和存储库。

谢谢你< 3.

1 个答案:

答案 0 :(得分:5)

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

// 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));
    }
}

在此示例中,您将从内到外构建模拟,首先创建由Repository返回的员工,该库本身由EntityManager返回。这样,测试就不会涉及真正的类。

资料来源: http://symfony.com/doc/current/testing/database.html