是否有Laravel框架条件可能会在测试期间截断模型表?
在测试我的Laravel应用程序时,我遇到了一个神秘的错误:在我调用Postjson
方法之后,在中间软件中找不到刚刚创建的模型实例。
测试类storeEventControllerTest
扩展了Laravel的testCase
,它使用lazilyrefresdatabase
。我已经尝试将其删除形成testCase
,还添加了RefreshDatabase
,无济于事。
我已经尝试调试测试,但仍然无法弄清楚发生了什么:
测试调试步骤#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 #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:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论