簡體   English   中英

在Laravel中設置PHPUnit測試

[英]Setting up PHPUnit tests in Laravel

我對單元測試很新,但我已經閱讀了很多關於phpunit.de的文檔(直到第10章)。

它指出使用數據庫進行測試可能很慢,但如果設置正確,它可以與非數據庫測試一樣快。

因此,我想在Laravel中測試一個模型。 我已經創建了一個模型工廠來將數據植入數據庫。

我也創建了一個基本測試。

在PHPUnits文檔中,它聲明在每次測試之前,調用setUp()方法來設置測試。 還有另一個靜態方法setUpBeforeClass()

我想只為我的數據庫表播種一次,並使用我的測試中的記錄。 所以我使用Laravels factory()函數從setUpBeforeClass()方法中為數據庫設定種子。

這是我的代碼:

class CommentTest extends TestCase
{
    protected static $blog;
    protected static $comments;

    public static function setUpBeforeClass()
    {
        parent::setUpBeforeClass();

        self::$blog = factory(App\Models\Content\Blog::class)->create();
        self::$comments = factory(App\Models\Content\Comment::class, 6)->create();
    }

    public function testSomething()
    {
        $this->assertTrue(true);
    }
}

但是,當我運行phpunit ,我收到以下錯誤:

Fatal error: Call to a member function make() on a non-object in \vendor\laravel\framework\src\Illuminate\Foundation\helpers.php on line 54

Call Stack:
    0.0002     240752   1. {main}() \vendor\phpunit\phpunit\phpunit:0
    0.0173    1168632   2. PHPUnit_TextUI_Command::main() \vendor\phpunit\phpunit\phpunit:47
    0.0173    1175304   3. PHPUnit_TextUI_Command->run() \vendor\phpunit\phpunit\src\TextUI\Command.php:100
    2.9397    5869416   4. PHPUnit_TextUI_TestRunner->doRun() \vendor\phpunit\phpunit\src\TextUI\Command.php:149
    2.9447    6077272   5. PHPUnit_Framework_TestSuite->run() \vendor\phpunit\phpunit\src\TextUI\TestRunner.php:440
    2.9459    6092880   6. PHPUnit_Framework_TestSuite->run() \vendor\phpunit\phpunit\src\Framework\TestSuite.php:747
    2.9555    6096160   7. call_user_func:{\vendor\phpunit\phpunit\src\Framework\TestSuite.php:697}() \vendor\phpunit\phpunit\src\Framework\TestSuite.php:697
    2.9555    6096272   8. CommentTest::setUpBeforeClass() \vendor\phpunit\phpunit\src\Framework\TestSuite.php:697
    2.9555    6096480   9. factory() \tests\CommentTest.php:18
    2.9556    6096656  10. app() \vendor\laravel\framework\src\Illuminate\Foundation\helpers.php:350

如果我將代碼從setUpBeforeClass()移動到setUp()並運行它,它會按預期工作,但這肯定是低效的,因為它為每個測試播種數據庫?

我的問題:

  1. 是從setUpBeforeClass()播種數據庫的正確方法嗎?
  2. 如果是(問題1),那么為什么我在運行phpunit時會遇到致命錯誤,在調用factory()之前我應該​​做些什么?
  3. 如果我必須將代碼放在setUp()方法中,是否會出現性能問題?
  4. 我是否應該從setUpBeforeClass()setUp()方法中播種? 在Laravels文檔中,它顯示了在測試中發生種子的示例,但是如果我正在運行100次測試(例如),播種100次是個好主意嗎?

好的,經過一些調查(類)后,我確定在調用靜態setUpBeforeClass()方法時尚未創建Laravel應用程序。

Laravel容器是在第一次在\\vendor\\laravel\\framework\\src\\illuminate\\Foundation\\Testing\\TestCase.php調用setUp()時創建的。 這就是我將代碼移動到setUp()方法時工作正常的原因。

然后將容器存儲在存儲在\\vendor\\laravel\\framework\\src\\illuminate\\Foundation\\Testing\\ApplicationTrait.php中的$app屬性中。

我可以通過將此代碼添加到setUpBeforeClass()方法來手動創建容器實例:

$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

但是這種方法看起來很糟糕,我不喜歡它。

相反,我將種子代碼移動到setUp ()方法,但只有在類屬性為null時才播種數據庫。 因此它只會在第一次調用setUp()時播種。 任何后續電話都不會播種:

class CommentTest extends TestCase
{
    use DatabaseMigrations;

    protected static $blog;
    protected static $comments;

    public function setUp()
    {
        parent::setUp();

        $this->runDatabaseMigrations();

        if (is_null(self::$blog)) {
            self::$blog = factory(App\Models\Content\Blog::class, 1)->create();
            self::$comments = factory(App\Models\Content\Comment::class, 6)->create();
        }
    }
}

結合Laravels DatabaseMigrations特性進行測試,現在是工作流程:

  1. 調用PHPUnit
  2. 調用Test類,其中包含DatabaseMigrations特征
  3. 遷移數據庫(創建表)
  4. 第一次調用setUp()方法,該方法使用測試數據對相關表進行種子處理
  5. 運行測試,並訪問測試數據
  6. 沒有調用tearDown()方法,而DatabaseMigrations特性只是重置數據庫,因此我的測試不必擔心清理測試數據。

編輯

此外,似乎(雖然我不是100%),如果你有一個自定義setUp()方法,你需要從重寫的setUp()方法手動調用runDatabaseMigrations()

public function setUp()
{
    parent::setUp();
    $this->runDatabaseMigrations();

    /** Rest of Setup **/
}

如果重載setUp()方法,似乎不會自動調用runDatabaseMigrations()

我希望這會有所幫助,但如果其他人有更好的解決方案,請隨時告訴我:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM