在 Laravel 中设置 PHPUnit 测试
问题描述
我对单元测试还很陌生,但我已经阅读了几乎所有关于 phpunit.de 的文档(直到第 10 章).
它指出使用数据库进行测试可能会很慢,但如果设置正确,它可以与非数据库测试一样快.
因此,我想在 Laravel 中测试一个模型.我创建了一个模型工厂来将数据播种到数据库中.
我还创建了一个基本测试.
在 PHPUnits 文档中,它声明在每次测试之前,都会调用 setUp() 方法来设置测试.还有另外一个静态方法setUpBeforeClass().
我只想为我的数据库表播种一次,并在我的测试中使用这些记录.所以我使用 Laravel 的 factory() 函数从 setUpBeforeClass() 方法中为数据库播种.
这是我的代码:
class CommentTest 扩展了 TestCase{受保护的静态 $blog;受保护的静态 $comments;公共静态函数 setUpBeforeClass(){父::setUpBeforeClass();self::$blog = factory(AppModelsContentBlog::class)->create();self::$comments = factory(AppModelsContentComment::class, 6)->create();}公共函数 testSomething(){$this->assertTrue(true);}}但是,当我运行 phpunit 时,出现以下错误:
致命错误:在第 54 行对 vendorlaravelframeworksrcIlluminateFoundationhelpers.php 中的非对象调用成员函数 make()调用堆栈:0.0002 240752 1. {main}() vendorphpunitphpunitphpunit:00.0173 1168632 2. PHPUnit_TextUI_Command::main() vendorphpunitphpunitphpunit:470.0173 1175304 3. PHPUnit_TextUI_Command->run() vendorphpunitphpunitsrcTextUICommand.php:1002.9397 5869416 4. PHPUnit_TextUI_TestRunner->doRun() vendorphpunitphpunitsrcTextUICommand.php:1492.9447 6077272 5. PHPUnit_Framework_TestSuite->run()vendorphpunitphpunitsrcTextUITestRunner.php:4402.9459 6092880 6. PHPUnit_Framework_TestSuite->run()vendorphpunitphpunitsrcFrameworkTestSuite.php:7472.9555 6096160 7. call_user_func:{vendorphpunitphpunitsrcFrameworkTestSuite.php:697}()vendorphpunitphpunitsrcFrameworkTestSuite.php:6972.9555 6096272 8. CommentTest::setUpBeforeClass() vendorphpunitphpunitsrcFrameworkTestSuite.php:6972.9555 6096480 9. factory() estsCommentTest.php:182.9556 6096656 10.app()vendorlaravelframeworksrcIlluminateFoundationhelpers.php:350如果我将代码从 setUpBeforeClass() 移动到 setUp() 并运行它,它会按预期工作,但这肯定是低效的,因为它为数据库播种每次测试?
我的问题:
在setUpBeforeClass()中为数据库播种是正确的方法吗?如果是(问题1),那么为什么我在运行phpunit时会遇到致命错误,在调用factory()之前我应该做什么?如果我必须将代码放在setUp()方法中,是否会出现性能问题?我什至应该从setUpBeforeClass()或setUp()方法中播种吗?在 Laravel 文档中,它显示了在测试本身中进行播种的示例,但如果我正在运行 100 个测试(例如),那么播种 100 次是个好主意吗?
解决方案 好的,经过一番调查(类),我确定 Laravel 应用程序在静态 setUpBeforeClass() 方法被调用.
Laravel 容器是在 vendorlaravelframeworksrcilluminateFoundationTestingTestCase.php 中第一次调用 setUp() 时创建的.这就是为什么当我将代码移动到 setUp() 方法时它可以正常工作的原因.
容器然后存储在 .p>vendorlaravelframeworksrcilluminateFoundationTestingApplicationTrait.php 中的 $app 属性中.
我可以通过将此代码添加到 setUpBeforeClass() 方法来手动创建容器实例:
但是这种方法看起来很hacky,我不喜欢它.
相反,我将播种代码移至 setUp() 方法,但仅在类属性为空时才播种数据库.因此,它只会在第一次调用 setUp() 时播种.任何后续调用都不会被播种:
结合 Laravel 的 DatabaseMigrations trait 进行测试,现在的工作流程如下:
- PHPUnit 被调用
- Test 类被调用,其中包含
DatabaseMigrationstrait - 迁移数据库(创建表)
- 第一次调用
setUp()方法,用测试数据播种相关表 - 运行测试,并访问测试数据
- 没有调用
tearDown()方法,而是DatabaseMigrationstrait 只是简单地重置数据库,所以我的测试不必担心清理测试数据.
编辑
另外,看起来(虽然我不是100%),如果你有自定义的setUp()方法,你需要手动调用runDatabaseMigrations() 从重写的 setUp() 方法:
