如何与数据库交互的测试代码
编辑该页面警告:你浏览的文档欧宝官网下载appob娱乐下载Symfony 5.1,不再维护。
读这个页面的更新版本Symfob娱乐下载ony 6.2(当前的稳定版本)。
如何与数据库交互的测试代码
配置数据库测试
与数据库交互的测试应该使用自己的单独的数据库不惹中使用的数据库配置环境。为此,编辑或创建.env.test.local
在项目的根目录文件和定义的新值DATABASE_URL
env var:
1 2
# .env.test.localDATABASE_URL =“mysql: / /用户名:PASSWORD@127.0.0.1:3306 / DB_NAME ? serverVersion = 5.7 "
提示
一个常见的实践是附加的_t
后缀在测试原始数据库的名称。如果生产的数据库名称project_acme
测试数据库的名称project_acme_test
。
上述假设每个开发人员/测试机器使用不同的数据库。如果整个测试团队使用相同的设置,编辑或创建.env.test
文件而不是提交到共享库中。了解更多关于使用多个.env Symfony应用程序中的文件ob娱乐下载。
在每个测试之前自动重置数据库
测试应该是独立于对方,避免副作用。例如,如果一些测试修改数据库(通过添加或删除一个实体),它可以改变其他测试的结果。运行以下命令安装包,确保每个测试运行相同的修改的数据库:
1
美元作曲家要求- dev dama / doctrine-test-bundle
现在,使它作为一个PHPUnit)扩展或侦听器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
< !——phpunit.xml。区域- - ><phpunit)>< !——……- - >< !——添加这个PHPUnit) 7.5或更高版本- - ><扩展><扩展类=“DAMA \ DoctrineTestBundle \ PHPUnit) \ PHPUnitExtension”/ >< /扩展>< !——添加这个PHPUnit) 7.0到7.4 - - ><听众><侦听器类=“\ DAMA \ DoctrineTestBundle \ PHPUnit) \ PHPUnitListener”/ >< /听众>< /phpunit)>
这个包使用一个聪明的技巧来避免副作用不牺牲性能:它开始一个数据库事务在每个测试之前和回滚测试完成后自动撤销所有的变化。阅读更多的文档欧宝官网下载appDAMADoctrineTestBundle。
虚拟数据设备
而不是使用真正的生产数据库的数据,通常使用假或虚拟测试数据库中的数据。这是通常被称为“设备数据”和原则提供了一个库来创建和加载它们。安装:
1
美元作曲家要求- dev / doctrine-fixtures-bundle教义
然后,使用:设备
命令来生成一个空夹具类:
1 2 3 4
美元php bin /控制台:夹具装置创建的类名(例如AppFixtures): > ProductFixture
自定义新的类加载产品
对象为原则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/ / src / DataFixtures / ProductFixture.php名称空间应用程序\DataFixtures;使用应用程序\实体\产品;使用学说\包\FixturesBundle\夹具;使用学说\持久性\ObjectManager;类ProductFixture扩展夹具{公共函数负载(ObjectManager美元经理){美元产品=新产品();美元产品- >setName (“无价的小部件”);美元产品- >setPrice (14.50);美元产品- >setDescription (‘好吧,我猜这* *有价格的);美元经理- >persist (美元产品);/ /添加更多的产品美元经理- >冲洗();}}
空的数据库并重新加载所有设备类:
1
美元php bin /控制台学说:夹具:负载
有关更多信息,阅读DoctrineFixturesBundle文欧宝官网下载app档。
在单元测试中嘲笑教义存储库
单元测试原则库不推荐。存储库是测试一个真正的数据库连接。然而,如果你仍然需要这样做,看看下面的例子。
假设您想要的类测试是这样的:
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 /工资/ SalaryCalculator.php名称空间应用程序\工资;使用应用程序\实体\员工;使用学说\持久性\ObjectManager;类SalaryCalculator{私人美元objectManager;公共函数__construct(ObjectManager美元objectManager){美元这- >objectManager =美元objectManager;}公共函数calculateTotalSalary(美元id){美元employeeRepository=美元这- >objectManager- >getRepository(员工::类);美元员工=美元employeeRepository- >找到(美元id);返回美元员工- >getSalary () +美元员工- >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
/ /测试/工资/ SalaryCalculatorTest.php名称空间应用程序\测试\工资;使用应用程序\实体\员工;使用应用程序\工资\SalaryCalculator;使用学说\持久性\ObjectManager;使用学说\持久性\ObjectRepository;使用PHPUnit)\框架\TestCase;类SalaryCalculatorTest扩展TestCase{公共函数testCalculateTotalSalary(){美元员工=新员工();美元员工- >setSalary (1000年);美元员工- >setBonus (1100年);/ /现在,模拟存储库返回员工的模拟美元employeeRepository=美元这- >createMock (ObjectRepository::类);/ /使用getMock PHPUnit) 5.3或以下()/ / $ employeeRepository = $ this - > getMock (ObjectRepository::类);美元employeeRepository- >预计(美元这- >任何())- >方法(“发现”)- >willReturn (美元员工);/ /最后,模拟EntityManager返回存储库的模拟/ /不需要(这类注入测试/ /存储库使用而不是整个对象管理器)美元objectManager=美元这- >createMock (ObjectManager::类);/ /使用getMock PHPUnit) 5.3或以下()/ / $ objectManager = $ this - > getMock (objectManager::类);美元objectManager- >预计(美元这- >任何())- >方法(“getRepository”)- >willReturn (美元employeeRepository);美元salaryCalculator=新SalaryCalculator (美元objectManager);美元这- >assertequal (2100年,美元salaryCalculator- >calculateTotalSalary (1));}}
在这个例子中,您正在构建模拟从内到外,第一个创建员工得到返回的存储库
,这本身得到返回的EntityManager
。这种方式,没有真正的类是参与测试。
功能测试的教义库
在功能测试你会使用实际的原则使查询数据库存储库,而不是嘲笑他们。为此,把实体管理器通过服务容器如下:
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
/ /测试/仓库/ 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 =零;}}