如何在内存中运行含MongoDB模型的Laravel测试(替代SQLite)
Laravel + MongoDB 测试:解决SQLite内存测试不兼容问题
你的问题核心是:Laravel默认的RefreshDatabase Trait和SQLite内存库是为关系型数据库设计的,而你的模型继承自MongoDB\Laravel\Eloquent\Model,连接的是MongoDB,SQLite根本不会存储MongoDB模型的数据,自然断言失败。以下是两种可行的内存测试方案:
方案1:使用MongoDB内存服务器(推荐)
MongoDB提供了专门的内存版服务器,完全在内存中运行,适合测试场景,速度快且无需持久化数据。
- 安装依赖
composer require --dev mongodb/mongodb mongodb/memory-server
- 配置测试环境数据库
在config/database.php的connections节点中确保MongoDB配置正确:
'mongodb' => [ 'driver' => 'mongodb', 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', 27017), 'database' => env('DB_DATABASE', 'laravel_test'), 'username' => env('DB_USERNAME'), 'password' => env('DB_PASSWORD'), 'options' => [ 'database' => 'admin' ], ],
然后在.env.testing中指定MongoDB为测试连接:
DB_CONNECTION=mongodb DB_DATABASE=laravel_test
- 自定义MongoDB数据清理Trait
替换Laravel默认的RefreshDatabase,因为它不兼容MongoDB:
namespace Tests\Traits; trait RefreshMongoDatabase { protected function setUp(): void { parent::setUp(); $this->clearMongoCollections(); } protected function clearMongoCollections() { $client = \MongoDB\Laravel\Facades\MongoDB::getClient(); $database = $client->selectDatabase(env('DB_DATABASE')); foreach ($database->listCollections() as $collection) { $database->selectCollection($collection->getName())->deleteMany([]); } } }
在测试类中使用这个Trait:
use Tests\Traits\RefreshMongoDatabase; class ProductTest extends TestCase { use RefreshMongoDatabase; public function test_if_product_can_be_created() { Product::create([ 'uuid' => '1234', ]); // 注意:你之前写错了集合名,应该是products而非owners $this->assertDatabaseCount('products', 1); } }
方案2:单测试类的临时集合清理
如果只是少量测试,也可以在单个测试类中手动处理集合清理:
class ProductTest extends TestCase { protected function setUp(): void { parent::setUp(); // 确保集合存在(可选) Product::getCollection(); } protected function tearDown(): void { // 测试后清空当前模型的集合 Product::getCollection()->deleteMany([]); parent::tearDown(); } public function test_if_product_can_be_created() { Product::create(['uuid' => '1234']); // 直接用模型count断言更直观 $this->assertEquals(1, Product::count()); } }
另外提醒:你测试代码中的assertDatabaseCount('owners', 1)是错误的,应该对应你的模型集合名products,这也是导致断言失败的直接原因之一。
内容的提问来源于stack exchange,提问作者Lucas Pace
相关产品推荐
相关产品推荐

