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 中运行单元测试