Sqlite 在单元测试中忽略数据库约束

Posted

技术标签:

【中文标题】Sqlite 在单元测试中忽略数据库约束【英文标题】:Sqlite ignore database constraints in unti test 【发布时间】:2020-03-15 04:59:16 【问题描述】:

我正在尝试根据一些相关的模型/数据库约束来测试我的数据库中的某个模型是否可以(或不能)被删除。

我在我的 Laravel 单元测试中使用 SQLite,但它似乎忽略了约束,并且当我分解未首先删除的相关模型时,总是允许在测试中进行删除而不会出错。

这只是一个 sqlite 的东西还是有一些我不知道的设置?

这是我的测试的简单版本

/** @test */
public function product_canot_be_deleted()

    $product = factory(Product::class)->create([
        'deletion_flag' => 1
    ]);
    factory(Service::class)->create([
        'product_id' => $product->id
    ]);

    $this->artisan('products:delete');

    $this->assertCount(1, Product::all());
    $this->assertCount(1, Service::all());

该命令仅循环遍历表中已标记为删除的所有产品。 此测试失败并允许删除产品。 当产品具有关联服务时,它不应被删除。相关行服务迁移文件如下所示

$table->integer('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products');

没有提及级联删除。

【问题讨论】:

sqlite 中默认禁用外键约束,参见here。你使用的是哪个 laravel 版本?它是在 laravel 5.7 中添加的,请参阅here。 我在 6.0.好的,我如何添加 foreign_key_constraints 设置?看起来正是我需要的。 根据docs,您可以在phpunit.xml 文件中添加DB_FOREIGN_KEYS=true 环境变量,类似于<env name="DB_FOREIGN_KEYS" value="true"/> 好的,想通了。在我的 PHPUnit.xml 中有这一行。 <env name="DB_CONNECTION" value="testing"/> 所以在database.php 配置文件中,我将此行添加到testing 块中:'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), 现在可以完美运行。感谢您的帮助。 @JohnHalsey:考虑添加你的答案。这更加明显,您还可以对其进行详细说明,代码示例/ sn-ps 等。这对 *** 最有效。一段时间后,您甚至可以接受自己的答案。只是说。 【参考方案1】:

sqlite 中默认禁用外键约束。

来自docs:

默认禁用外键约束(用于向后 兼容性),因此必须为每个数据库单独启用 联系。 (但是请注意,SQLite 的未来版本可能 更改以便默认启用外键约束。小心 开发商不会对是否外国做任何假设 默认情况下启用键,但将启用或禁用它们 必要的。)

在5.7 中,Laravel 添加了一个启用外键的配置选项,因此您可以执行以下操作:

Docs

要为 SQLite 连接启用外键约束,您应该 将 DB_FOREIGN_KEYS 环境变量设置为 true:

DB_FOREIGN_KEYS=true

或者您可以将foreign_key_constraints 添加到您的数据库配置中:

Docs

要为 SQLite 连接启用外键约束,您应该 将 foreign_key_constraints 选项添加到您的 config/database.php 配置文件:

'sqlite' => [
    // ...
    'foreign_key_constraints' => true,
],

【讨论】:

以上是关于Sqlite 在单元测试中忽略数据库约束的主要内容,如果未能解决你的问题,请参考以下文章

如何使用内存数据库中的 sqlite 在 laravel 5.5 中运行单元测试

以编程方式测试视图约束(在单元测试中)

使用 SQLite3 进行单元测试

Laravel 忽略测试数据库连接

Django:在运行单元测试之前创建测试表时“无法添加外键约束”

带有预加载 sqlite3 数据库的 iOS 单元测试