沃梦达 / 编程问答 / php问题 / 正文

在 Laravel 中设置 PHPUnit 测试

Setting up PHPUnit tests in Laravel(在 Laravel 中设置 PHPUnit 测试)

本文介绍了在 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() 并运行它,它会按预期工作,但这肯定是低效的,因为它为数据库播种每次测试?

我的问题:

  1. setUpBeforeClass() 中为数据库播种是正确的方法吗?
  2. 如果是(问题1),那么为什么我在运行phpunit时会遇到致命错误,在调用factory()之前我应该​​做什么?
  3. 如果我必须将代码放在 setUp() 方法中,是否会出现性能问题?
  4. 我什至应该从 setUpBeforeClass()setUp() 方法中播种吗?在 Laravel 文档中,它显示了在测试本身中进行播种的示例,但如果我正在运行 100 个测试(例如),那么播种 100 次是个好主意吗?

解决方案

好的,经过一番调查(类),我确定 Laravel 应用程序在静态 setUpBeforeClass() 方法被调用.

Laravel 容器是在 vendorlaravelframeworksrcilluminateFoundationTestingTestCase.php 中第一次调用 setUp() 时创建的.这就是为什么当我将代码移动到 setUp() 方法时它可以正常工作的原因.

容器然后存储在 vendorlaravelframeworksrcilluminateFoundationTestingApplicationTrait.php 中的 $app 属性中..p>

我可以通过将此代码添加到 setUpBeforeClass() 方法来手动创建容器实例:

$app = 需要 __DIR__.'/../bootstrap/app.php';$app->make(IlluminateContractsConsoleKernel::class)->bootstrap();

但是这种方法看起来很hacky,我不喜欢它.

相反,我将播种代码移至 setUp() 方法,但仅在类属性为空时才播种数据库.因此,它只会在第一次调用 setUp() 时播种.任何后续调用都不会被播种:

class CommentTest 扩展了 TestCase{使用数据库迁移;受保护的静态 $blog;受保护的静态 $comments;公共函数设置(){父::setUp();$this->runDatabaseMigrations();if (is_null(self::$blog)) {self::$blog = factory(AppModelsContentBlog::class, 1)->create();self::$comments = factory(AppModelsContentComment::class, 6)->create();}}}

结合 Laravel 的 DatabaseMigrations trait 进行测试,现在的工作流程如下:

  1. PHPUnit 被调用
  2. Test 类被调用,其中包含 DatabaseMigrations trait
  3. 迁移数据库(创建表)
  4. 第一次调用setUp()方法,用测试数据播种相关表
  5. 运行测试,并访问测试数据
  6. 没有调用 tearDown() 方法,而是 DatabaseMigrations trait 只是简单地重置数据库,所以我的测试不必担心清理测试数据.

编辑

另外,看起来(虽然我不是100%),如果你有自定义的setUp()方法,你需要手动调用runDatabaseMigrations() 从重写的 setUp() 方法:

公共函数 setUp(){父::setUp();$this->runDatabaseMigrations();/** 其余设置 **

本文标题为:在 Laravel 中设置 PHPUnit 测试

基础教程推荐