Як тестувати сховище Doctrine
Дата оновлення перекладу 2022-11-24
Як тестувати сховище Doctrine
See also
Головне керівництво з Тестування описує, як використовувати та встановлювати базу даних для ваших автоматизованих тестів. Зміст цієї статті демонструє шляхи тестування ваших сховищ Doctrine.
Імітація сховища Doctrine у модульних тестах
Модульне тестування сховищ Doctrine не рекомендовано. Сховища повинні тестуватися з реальним зʼєднанням бази даних. Однак, у випадку, якщо вам все одно треба це зробити, розгляньте наступний приклад.
Припустимо, що клас, який ви хочете протестувати, виглядає так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// src/Salary/SalaryCalculator.php
namespace App\Salary;
use App\Entity\Employee;
use Doctrine\Persistence\ObjectManager;
class SalaryCalculator
{
private $objectManager;
public function __construct(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
public function calculateTotalSalary($id)
{
$employeeRepository = $this->objectManager
->getRepository(Employee::class);
$employee = $employeeRepository->find($id);
return $employee->getSalary() + $employee->getBonus();
}
}
Так як EntityManagerInterface
впроваджується у клас через конструктор,
ви можете передати зімітований обʼєкт у тесті:
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/Salary/SalaryCalculatorTest.php
namespace App\Tests\Salary;
use App\Entity\Employee;
use App\Salary\SalaryCalculator;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Persistence\ObjectRepository;
use PHPUnit\Framework\TestCase;
class SalaryCalculatorTest extends TestCase
{
public function testCalculateTotalSalary()
{
$employee = new Employee();
$employee->setSalary(1000);
$employee->setBonus(1100);
// Тепер, зімітуйте сховище, щоб воно повертало імітацію робітника
$employeeRepository = $this->createMock(ObjectRepository::class);
// використайте getMock() в PHPUnit 5.3 або нижче
// $employeeRepository = $this->getMock(ObjectRepository::class);
$employeeRepository->expects($this->any())
->method('find')
->willReturn($employee);
// Нарешті, зімітуйте EntityManager, щоб повернути імітацію сховища
// (це не потрібно, якщо тестований клас впроваджує сховище, яке
// він використовує, замість всього менеджеру обʼєктів)
$objectManager = $this->createMock(ObjectManager::class);
// використайте getMock() в PHPUnit 5.3 або нижче
// $objectManager = $this->getMock(ObjectManager::class);
$objectManager->expects($this->any())
->method('getRepository')
->willReturn($employeeRepository);
$salaryCalculator = new SalaryCalculator($objectManager);
$this->assertEquals(2100, $salaryCalculator->calculateTotalSalary(1));
}
}
У цьому прикладі, ви будуєте імітації зсередини назовні, спочатку створюючи
робітника, який повертається Repository
, яке, в свою чергу, повертається
EntityManager
. Таким чином, жодний реальний клас не задіяний у тестуванні.
Функціональне тестування сховища Doctrine
У функціональних тестах ви робитимете запити до бази даних, використовуючи реальні сховища Doctrine, замість їх імітації. Щоб зробити це, отримайте менеджер сутностей через сервіс-контейнер наступним чином:
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 40 41
// tests/Repository/ProductRepositoryTest.php
namespace App\Tests\Repository;
use App\Entity\Product;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class ProductRepositoryTest extends KernelTestCase
{
/**
* @var \Doctrine\ORM\EntityManager
*/
private $entityManager;
protected function setUp(): void
{
$kernel = self::bootKernel();
$this->entityManager = $kernel->getContainer()
->get('doctrine')
->getManager();
}
public function testSearchByName()
{
$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;
}
}