如何测试 Doctrine 仓库
另请参阅
主要测试指南 介绍了如何在自动化测试中使用和设置数据库。本文内容展示了测试 Doctrine 仓库的方法。
在单元测试中 Mock Doctrine 仓库
不建议对 Doctrine 仓库进行单元测试。仓库应该针对真实的数据库连接进行测试。但是,如果您仍然需要这样做,请查看以下示例。
假设您要测试的类如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// src/Salary/SalaryCalculator.php
namespace App\Salary;
use App\Entity\Employee;
use Doctrine\ORM\EntityManager;
class SalaryCalculator
{
public function __construct(
private EntityManager $entityManager,
) {
}
public function calculateTotalSalary(int $id): int
{
$employeeRepository = $this->entityManager
->getRepository(Employee::class);
$employee = $employeeRepository->find($id);
return $employee->getSalary() + $employee->getBonus();
}
}
由于 EntityManagerInterface
通过构造函数注入到类中,您可以在测试中传递一个 mock 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// tests/Salary/SalaryCalculatorTest.php
namespace App\Tests\Salary;
use App\Entity\Employee;
use App\Salary\SalaryCalculator;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use PHPUnit\Framework\TestCase;
class SalaryCalculatorTest extends TestCase
{
public function testCalculateTotalSalary(): void
{
$employee = new Employee();
$employee->setSalary(1000);
$employee->setBonus(1100);
// Now, mock the repository so it returns the mock of the employee
$employeeRepository = $this->createMock(EntityRepository::class);
$employeeRepository->expects($this->any())
->method('find')
->willReturn($employee);
// Last, mock the EntityManager to return the mock of the repository
// (this is not needed if the class being tested injects the
// repository it uses instead of the entire entity manager)
$entityManager = $this->createMock(EntityManager::class);
$entityManager->expects($this->any())
->method('getRepository')
->willReturn($employeeRepository);
$salaryCalculator = new SalaryCalculator($entityManager);
$this->assertEquals(2100, $salaryCalculator->calculateTotalSalary(1));
}
}
在本例中,您是从内向外构建 mocks,首先创建 employee,它由 Repository
返回,而 Repository
本身又由 EntityManager
返回。这样,测试中不涉及任何真实的类。
Doctrine 仓库的功能测试
在 功能测试 中,您将使用实际的 Doctrine 仓库向数据库发出查询,而不是 mock 它们。为此,请通过服务容器获取实体管理器,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
// tests/Repository/ProductRepositoryTest.php
namespace App\Tests\Repository;
use App\Entity\Product;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class ProductRepositoryTest extends KernelTestCase
{
private ?EntityManager $entityManager;
protected function setUp(): void
{
$kernel = self::bootKernel();
$this->entityManager = $kernel->getContainer()
->get('doctrine')
->getManager();
}
public function testSearchByName(): void
{
$product = $this->entityManager
->getRepository(Product::class)
->findOneBy(['name' => 'Priceless widget'])
;
$this->assertSame(14.50, $product->getPrice());
}
protected function tearDown(): void
{
parent::tearDown();
// doing this is recommended to avoid memory leaks
$this->entityManager->close();
$this->entityManager = null;
}
}
这项工作,包括代码示例,根据 Creative Commons BY-SA 3.0 许可证获得许可。