【问题标题】:Laravel 5 testing in memoryLaravel 5 内存测试
【发布时间】:2015-08-14 21:17:19
【问题描述】:

我正在通过 behat 为我的大型 Laravel 5 项目编写测试。

我在 MySQL 中有一个我的 MySQL 数据库的测试副本和一个用于该数据库的种子器,它共享其他环境的一些种子器。所有这些都按预期工作。

但是,我尝试切换到使用 sqlite 内存数据库,因为它会显着加快我的自动化测试速度,并且因为我在每个 behat 场景开始时都运行“artsian migrate:refresh ---seeder=TestDatabaseSeeder。

我遇到的问题是我的一些种子数据导致 sqlite 抛出一个非常难以描述的语法错误,但 MySQL 对种子数据完全没问题。

我认为,理想情况下,我希望它使用内存中的 MySQL 来提高性能并保持数据库引擎的一致性。在运行测试时,是否有一种简单的方法可以使用或不使用 Laravel 在内存中使用 MySQL?不涉及以使 sqlite 满意的方式复制和编辑迁移文件的解决方案?

【问题讨论】:

  • 好吧,水晶球是个神话,所以恐怕你应该提供一些你面临的错误信息,相关代码/模式等让我们看看
  • 您可以尝试查看允许内存表的MySQL MEMORY Storage Engine。然而,这确实有一些缺点,例如不支持外键,这在大多数情况下可能会破坏交易。
  • 您应该编辑您的问题并添加此新信息。不是每个人都阅读 cmets。此外,如果您解决了问题,您可以自己添加答案,以便未来的读者也从您的经验中受益。您甚至可以在 48 小时后接受自己的答案。

标签: mysql sqlite laravel behat in-memory-database


【解决方案1】:

截至 2019 年,这是让 Laravel PHPunit 测试使用内存数据库的方法。

为 Laravel / Lumen 测试设置 SQLite In-memory

您必须具备以下条件:

  1. 数据库中所有表和文件的所有数据库迁移,就像您通常对实际数据库所做的那样,请参阅Laravel migrations official docs
  2. 在您的 PHPUnit 测试类 (official docs) 中使用 RefreshDatabase 特征(DatabaseMigrations 特征表示 Lumen)。
  3. config/database.php 文件的connection 设置中设置以下内容:
    'testing' => [
        'driver' => 'sqlite',
        'database' => ':memory:',
    ],
  1. phpunit.xml 文件的<php> 部分中设置以下行:
    <env name="DB_CONNECTION" value="testing"/>

因此,一旦您运行 PHPUnit 测试,PHPUnit 就会读取 phpunit.xml,将 .envDB_CONNECTION 变量替换为 testing。它将触发要使用的数据库配置testing(内存中的sqlite DB)。

内存数据库与磁盘数据库的测试(根据我的经验)要快约 5-30 倍。 30 倍的差异是针对约 200 个 CRUD 的小型测试套件测试所有在六个表上运行的数据库查询,这些表具有一些 hasManybelongsToMany 透视关系。

为每个测试刷新数据库

要运行数据库迁移 to have a clean database before each test 在测试类 (Laravel) 的顶部添加以下特征:

use Illuminate\Foundation\Testing\RefreshDatabase;
// ... then in the class body:
use RefreshDatabase;

对于流明it should be

use Laravel\Lumen\Testing\DatabaseMigrations;
// ...then
use DatabaseMigrations;

如果需要,不要忘记使用model factories 为数据库播种测试数据。

是的,迁移将在每次测试之前和之后运行,因此您可以在测试完成后使用干净的数据库开始和结束(如果您在磁盘数据库中植入一些数据并偶尔切换,这将产生影响在其上运行的测试,而不是在内存数据库上运行)。

修复 SQLite Cannot add a NOT NULL column with default value NULL 错误

现在您已成功为您的应用设置内存数据库测试。当您尝试使用外键对某些相关表进行级联更改时,预计会出现上述错误。

如果您快速将测试切换到磁盘数据库(在您的 phpunit.xml 文件中注释掉 &lt;env name="DB_CONNECTION" value="testing"/&gt;),错误就会消失。切换回内存数据库后,检查您的磁盘数据库是否为空。如果是这样,使用artisan 运行migrate:refreshdb:seed(这里假设您之前已经准备好所需的数据库种子)。

默认情况下,SQLite 禁用外键。将以下 sn-ps 添加到您的 PHPUnit 测试类以解决此问题:

// At the file's top to import the DB facade
use Illuminate\Support\Facades\DB;


// In the setUp() method
parent::setUp();
if (DB::connection() instanceof \Illuminate\Database\SQLiteConnection) {
    DB::statement(DB::raw('PRAGMA foreign_keys=on'));
}

detailed explanations and more, better, different solutions here

希望这足以阐明主题以无缝地工作。

【讨论】:

    【解决方案2】:

    原来 sqlite 不喜欢 ' 被转义的方式。

    “\'”需要替换为“''”。而且 sqlite 不支持枚举,所以我改变了我的迁移并使用字符串而不是枚举。

    【讨论】:

    • 这不是那个问题的答案-
    猜你喜欢
    • 1970-01-01
    • 2016-12-30
    • 2016-06-04
    • 2016-07-28
    • 2018-03-31
    • 2021-02-09
    • 2016-07-18
    • 2014-12-19
    • 2015-10-14
    相关资源
    最近更新 更多