是否有Laravel框架条件可能会在测试期间截断模型表?

发布于 2025-01-23 22:50:21 字数 4310 浏览 0 评论 0原文

在测试我的Laravel应用程序时,我遇到了一个神秘的错误:在我调用Postjson方法之后,在中间软件中找不到刚刚创建的模型实例。

测试类storeEventControllerTest扩展了Laravel的testCase,它使用lazilyrefresdatabase。我已经尝试将其删除形成testCase,还添加了RefreshDatabase,无济于事。

我已经尝试调试测试,但仍然无法弄清楚发生了什么:

测试调试步骤#1:创建了模型实例

“测试调试步骤#1:创建了模型实例”

测试调查步骤2 :找不到最近创建的模型!

路由是在routes/api.php中配置的:

Route::post('stores/{key}/receive-payload', StoreEventController::class)
    ->middleware('event.signature')
    ->name('stores.receive-payload');

中间件event.signature.signature 句柄方法:

public function handle(Request $request, Closure $next)
{
    $key = $request->route('key');
    $sourceName = $request->get('source');

    if (!$key || !$sourceName) {
        abort(401);
    }

    /** @var EventStore $store */
    if (!$store = EventStore::find($key)) {
        abort(401);
    }

    /** @var EventStoreSource $source */
    if (!$source = $store->sources()->where('name', $sourceName)->first()) {
        abort(401);
    }

    $providedSignature = $this->getProvidedSignature($request, $source);

    if (!$providedSignature) {
        abort(401);
    }

    if (!$this->checkSignature($providedSignature, $request, $store, $source)) {
        abort(401);
    }

    // Bind the event store to the request so that it can be used in the controller
    app()->instance(EventStoreSource::class, $source);

    return $next($request);
}

这是Model EventStore的相关摘录:

use App\Models\Concerns\UsesUuidKey;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;

class EventStore extends Model
{
    use HasFactory;

    use UsesUuidKey;

namespace App\Models\Concerns;

use Illuminate\Support\Str;

trait UsesUuidKey
{
    public function initializeUsesUuidKey()
    {
        $this->setKeyType('string');

        $this->setIncrementing(false);
    }

    public static function bootUsesUuidKey()
    {
        static::creating(fn ($model) => $model->setUuidKey());
    }

    protected function setUuidKey()
    {
        $keyName = $this->getKeyName();

        if (blank($this->getAttribute($keyName))) {
            $this->setAttribute($keyName, Str::uuid());
        }
    }
}

Table event_stores结构:

+--------------+---------------------+------+-----+---------+-------+
| Field        | Type                | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+-------+
| id           | varchar(191)        | NO   | PRI | NULL    |       |
| team_id      | bigint(20) unsigned | YES  | MUL | NULL    |       |
| name         | varchar(191)        | NO   |     | NULL    |       |
| secret       | text                | NO   |     | NULL    |       |
| created_at   | timestamp           | YES  |     | NULL    |       |
| updated_at   | timestamp           | YES  |     | NULL    |       |
| activated_at | timestamp           | YES  |     | NULL    |       |
| config       | json                | YES  |     | NULL    |       |
| sources      | json                | YES  |     | NULL    |       |
+--------------+---------------------+------+-----+---------+-------+

在测试期间,我在调试控制台上运行了一些额外的命令,证明数据库连接在整个过程中不会发生变化:

编辑:我添加了表描述。 编辑2:在运行命令打印DB连接名称后,添加了调试控制台的屏幕截图。

I've encountered a mysterious error while testing my Laravel app: a model instance that's just been created is not found inside the middleware after I call postJson method.

The test class StoreEventControllerTest extends Laravel's TestCase, which is using LazilyRefreshesDatabase. I've tried removing it form the TestCase and also added RefreshDatabase, to no avail.

I've tried debugging the test, but still couldn't figure out what's going on:

Test debugging step #1: A model instance's been created

Test debugging step #1: A model instance's been created

Test debugging step #2: The recently created model is not found!

Test debugging step #2: The recently created model is not found!

Route is configured in routes/api.php:

Route::post('stores/{key}/receive-payload', StoreEventController::class)
    ->middleware('event.signature')
    ->name('stores.receive-payload');

The middleware event.signature handle method:

public function handle(Request $request, Closure $next)
{
    $key = $request->route('key');
    $sourceName = $request->get('source');

    if (!$key || !$sourceName) {
        abort(401);
    }

    /** @var EventStore $store */
    if (!$store = EventStore::find($key)) {
        abort(401);
    }

    /** @var EventStoreSource $source */
    if (!$source = $store->sources()->where('name', $sourceName)->first()) {
        abort(401);
    }

    $providedSignature = $this->getProvidedSignature($request, $source);

    if (!$providedSignature) {
        abort(401);
    }

    if (!$this->checkSignature($providedSignature, $request, $store, $source)) {
        abort(401);
    }

    // Bind the event store to the request so that it can be used in the controller
    app()->instance(EventStoreSource::class, $source);

    return $next($request);
}

And here is a relevant excerpt from model EventStore:

use App\Models\Concerns\UsesUuidKey;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;

class EventStore extends Model
{
    use HasFactory;

    use UsesUuidKey;

namespace App\Models\Concerns;

use Illuminate\Support\Str;

trait UsesUuidKey
{
    public function initializeUsesUuidKey()
    {
        $this->setKeyType('string');

        $this->setIncrementing(false);
    }

    public static function bootUsesUuidKey()
    {
        static::creating(fn ($model) => $model->setUuidKey());
    }

    protected function setUuidKey()
    {
        $keyName = $this->getKeyName();

        if (blank($this->getAttribute($keyName))) {
            $this->setAttribute($keyName, Str::uuid());
        }
    }
}

The table event_stores structure:

+--------------+---------------------+------+-----+---------+-------+
| Field        | Type                | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+-------+
| id           | varchar(191)        | NO   | PRI | NULL    |       |
| team_id      | bigint(20) unsigned | YES  | MUL | NULL    |       |
| name         | varchar(191)        | NO   |     | NULL    |       |
| secret       | text                | NO   |     | NULL    |       |
| created_at   | timestamp           | YES  |     | NULL    |       |
| updated_at   | timestamp           | YES  |     | NULL    |       |
| activated_at | timestamp           | YES  |     | NULL    |       |
| config       | json                | YES  |     | NULL    |       |
| sources      | json                | YES  |     | NULL    |       |
+--------------+---------------------+------+-----+---------+-------+

Here's some extra commands I ran on the debug console during the test, which demonstrate the database connection doesn't change during the whole process:
enter image description here

Edit: I've added the table description.
Edit 2: Added a screenshot of the debug console after running commands to print the DB connection name.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文