You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在内存中运行含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 07:35:23