如何测试与数据库交互的代码
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 5.0,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
如何测试与数据库交互的代码
为测试配置数据库
与数据库交互的测试应该使用自己的单独数据库,以免与其他数据库中使用的数据库混淆配置环境.要做到这一点,请编辑或创建.env.test.local
文件的根目录,并为DATABASE_URL
env var:
1 2
# .env.test.localDATABASE_URL = mysql: / /用户名:PASSWORD@127.0.0.1 / DB_NAME
提示
一个常见的做法是附加_t
测试中原始数据库名称的后缀。如果生产中的数据库名称被调用project_acme
测试数据库的名称可以是project_acme_test
.
上面假设每个开发人员/机器使用不同的数据库进行测试。如果整个团队对测试使用相同的设置,请编辑或创建.env.test
文件,并将其提交到共享存储库。了解更多在Symfony应用程序中使用多个.env文件ob娱乐下载.
每次测试前自动重置数据库
测试应该相互独立,以避免副作用。例如,如果某个测试修改了数据库(通过添加或删除实体),它可能会更改其他测试的结果。运行以下命令来安装一个包,以确保每个测试都在相同的未修改的数据库中运行:
1
$Composer require——dev dama/doctrine-test-bundle
现在,启用它作为PHPUnit扩展或监听器:
12 3 4 5 6 7 8 9 10 11 12 13 14
<!——phpunit.xml.dist——><phpunit)><!——……--><!为PHPUnit 7.5或更高版本添加此功能<扩展><扩展类=“DAMA \ DoctrineTestBundle \ PHPUnit) \ PHPUnitExtension”/>扩展><!——PHPUnit 7.0到7.4添加这个<听众><侦听器类=“\ DAMA \ DoctrineTestBundle \ PHPUnit) \ PHPUnitListener”/>听众>phpunit)>
这个包使用了一个聪明的技巧来避免副作用而不牺牲性能:它在每次测试之前开始一个数据库事务,并在测试结束后自动回滚它以撤销所有更改。的文档中了解更多信息欧宝官网下载appDAMADoctrineTestBundle.
虚拟数据夹具
与使用来自生产数据库的真实数据不同,通常在测试数据库中使用假数据或虚拟数据。这通常被称为“设备数据”Doctrine提供了一个库来创建和加载它们。安装方法:
1
$编写人员需要—dev doctrine/doctrine-fixture -bundle
然后,使用:设备
命令生成一个空的fixture类:
1 2 3 4
$要创建的fixture的类名(例如AppFixtures): > ProductFixture
自定义要加载的新类产品
纳入教义的对象:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21 22
/ / src / DataFixtures / ProductFixture.php名称空间应用程序\DataFixtures;使用应用程序\实体\产品;使用学说\包\FixturesBundle\夹具;使用学说\持久性\ObjectManager;类ProductFixture扩展夹具{公共函数负载(ObjectManager$经理){$产品=新产品();$产品->setName (“无价的小部件”);$产品->setPrice (14.50);$产品->setDescription (“好吧,我想它的确是有价格的”);$经理->persist ($产品);//添加更多的产品$经理->冲洗();}}
清空数据库并重新加载所有fixture类具有:
1
$PHP bin/控制台原则:fixture:load
有关更多信息,请阅读DoctrineFixturesBundle文欧宝官网下载app档.
在单元测试中模拟理论存储库
不建议使用单元测试原则存储库.存储库是针对真实的数据库连接进行测试的。但是,如果您仍然需要这样做,请查看下面的示例。
假设你想要测试的类是这样的:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/ / src /工资/ SalaryCalculator.php名称空间应用程序\工资;使用应用程序\实体\员工;使用学说\持久性\ObjectManager;类SalaryCalculator{私人$objectManager;公共函数__construct(ObjectManager$objectManager){$这->objectManager =$objectManager;}公共函数calculateTotalSalary($id){$employeeRepository=$这->objectManager->getRepository(员工::类);$员工=$employeeRepository->找到($id);返回$员工->getSalary () +$员工->getBonus ();}}
自EntityManagerInterface
通过构造函数注入到类中,您可以在测试中传递一个模拟对象:
12 34 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
/ /测试/工资/ SalaryCalculatorTest.php名称空间应用程序\测试\工资;使用应用程序\实体\员工;使用应用程序\工资\SalaryCalculator;使用学说\持久性\ObjectManager;使用学说\持久性\ObjectRepository;使用PHPUnit)\框架\TestCase;类SalaryCalculatorTest扩展TestCase{公共函数testCalculateTotalSalary(){$员工=新员工();$员工->setSalary (1000);$员工->setBonus (1100);//现在,模拟存储库,使其返回员工的模拟$employeeRepository=$这->createMock (ObjectRepository::类);//在PHPUnit 5.3或以下使用getMock(// $employeeRepository = $this->getMock(ObjectRepository::class);$employeeRepository->预计($这->任何())->方法(“发现”)->willReturn ($员工);//最后,模拟EntityManager以返回存储库的模拟//(如果被测试的类注入//它使用的存储库而不是整个对象管理器)$objectManager=$这->createMock (ObjectManager::类);//在PHPUnit 5.3或以下使用getMock(// $this->getMock(objectManager::class);$objectManager->预计($这->任何())->方法(“getRepository”)->willReturn ($employeeRepository);$salaryCalculator=新SalaryCalculator ($objectManager);$这->assertequal (2100,$salaryCalculator->calculateTotalSalary (1));}}
在本例中,您将由内而外构建模拟,首先创建由对象返回的雇员存储库
函数返回EntityManager
.这样,测试中就不涉及真正的类。
理论存储库的功能测试
在功能测试您将使用实际的Doctrine存储库对数据库进行查询,而不是模仿它们。为此,通过服务容器获取实体管理器,如下所示:
12 34 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
/ /测试/仓库/ ProductRepositoryTest.php名称空间应用程序\测试\存储库;使用应用程序\实体\产品;使用ob娱乐下载\包\FrameworkBundle\测试\KernelTestCase;类ProductRepositoryTest扩展KernelTestCase{/ * * *@var\学说\ ORM \ EntityManager * /私人$entityManager;受保护的函数设置():无效{$内核=自我::bootKernel ();$这->entityManager =$内核->getContainer ()->get (“原则”)->getManager ();}公共函数testSearchByName(){$产品=$这->entityManager->getRepository(产品::类)->findOneBy ([“名字”= >“无价的小部件”]);$这->assertSame (14.50,$产品->getPrice ());}受保护的函数拆卸():无效{父::tearDown ();//建议这样做以避免内存泄漏$这->entityManager->close ();$这->entityManager =零;}}