如何为PHPUnit测试创建一个内存数据库?

6
我是PHPUnit(和单元测试)的新手。我想要开发一个测试套件:开发人员可以在本地运行,但也可以在我们的集成系统(Codeship)中运行。我了解到可以使用内存数据库,但似乎这取决于迁移,而我们没有使用(似乎无法很好地处理视图、存储过程、函数、触发器等)。在Laravel中,最好的方法(位置)是什么?用默认数据填充内存数据库(用于所有测试)。

可能是如何使MySQL数据库完全在内存中运行?的重复问题。 - hakre
1
@harkre,绝对没有重复,但它可以提供一些实现结果的提示。 - 8ctopus
2个回答

7

您可以使用SQLite。

从文档中可以得知:

SQLite数据库通常存储在单个普通磁盘文件中。但是,在某些情况下,数据库可能存储在内存中。

将以下内容添加到config/database.php文件中:

'sqlite_testing' => [
    'driver'   => 'sqlite',
    'database' => ':memory:',
    'prefix'   => '',
],

phpunit.xml 文件中,在 <php> 节点下:
<env name="DB_CONNECTION" value="sqlite_testing" />

请点击此处以了解更多相关的IT技术内容。

其他解决方案

storage/文件夹中创建一个名为database.sqlite的测试数据库,如果您想要另一个名称或位置,则必须更改config/database.php文件中的配置信息。以下是默认配置:

'sqlite' => [
    'driver'   => 'sqlite',
    'database' => storage_path('database.sqlite'),
    'prefix'   => '',
],

使用此命令运行您的迁移:

php artisan migrate --database=sqlite

或者将这一行添加到.env文件中:

DB_CONNECTION=sqlite

您的应用程序在使用sqlite进行phpunit测试。

现在,您可以运行迁移和测试。完成后,只需将DB_CONNECTION更改为您在项目中使用的数据库即可。


2
谢谢!看起来我会遇到一个问题,因为我们的数据库使用了大量不同的数据类型和其他结构,这些结构显然不受sqllite支持。所以似乎我必须确实有一个可用的mysql数据库。 - QuietSeditionist
你也可以使用 Travis CI 进行测试。如果你不想使用 SQLite,Travis CI 允许你配置像 MySQL 和 PgSQL(我通常使用)这样的数据库来进行测试。对于本地机器上的测试,我认为你可以无问题地使用 MySQL。 - Mateus Junges

7
这不是您可能在寻找的答案,而是另一种需要考虑的替代解决方案。
从我的经验来看,最简单的路径是模拟您的模型(或查询构建器,如果您正在使用它),并让它们返回您需要的结果。
在开发测试时,您应始终考虑可以完全删除哪些依赖项,以便您仅关注当前要测试的内容。
还可能存在微小差别(最可能非常微小)在运行内存数据库与生产数据库如何工作之间,这最终会损害测试的完整性,并且可能会给您带来误报。 如果您使用查询构建器,则特别是真实环境中需要开发不同的查询(例如MySQL和sqlite之间的不同语法)才能使查询本身正常工作。

1
那么在这种情况下,数据库交互根本没有得到测试? - QuietSeditionist
1
这真的取决于情况。如果您使用查询构建器编写自己的查询,那么您可能确实需要对其进行测试,并使用实际数据库(我建议设置一个分离的数据库服务器进行种子数据和测试)。但是,如果您正在使用Eloquent方法和关系,则不需要测试这些交互,因为Laravel开发人员已经处理了这些测试。模拟返回特定数据以用于测试的这些类型依赖项应该足够。 - user1669496
这并不是一个好主意,因为当模块之间的集成出现错误或者数据库 API 本身存在错误时,它可能不会被捕获。另一个缺点是,在测试中模拟数据库层会使测试与当前数据库实现紧密耦合,这增加了测试的刚性,并使未来的更改更加困难。 - Danon
你可以提供一个示例来说明如何实现它,这将是你的帖子的很好补充。 - 8ctopus
我建议在单元测试中使用模拟(_这个答案的建议_),在集成测试中使用运行(测试)数据库。 - ozanmuyes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接