Laravel策略在测试中的工作方式不同



Laravel 7.我使用 http 测试来检查我的页面的可用性状态。但我注意到在测试中,我的一个策略的工作方式不同。

控制器方法:

public function show(Competition $competition)
{
$competition->load('registeredTeams.user', 'teams.user');
return view('competitions.show', compact('competition'));
}

应用于它的策略方法:

public function view(User $user, Competition $competition)
{
return $user->id === $competition->user_id;
}

测试及其内部方法:

public function testCompetitionsPageTest()
{
$user = $this->loginAsFakeUser();
$user->commissioner = true;
$user->save();
$competition = $this->createFakeCompetition($user->id);
$this->get('/competitions')->assertOk();
$this->get('/competitions/create')->assertOk();
$this->get('/competitions/' . $competition->id)->assertOk();
}
protected function loginAsFakeUser()
{
$user = User::create(['username' => 'TestUserForTests']);
$this->actingAs($user);
return $user;
}
protected function createFakeCompetition(int $user_id)
{
$competition = new Competition([
'name' => 'TestCompetitionName',
'type' => competitionTypes()[2],
'tops_number' => 1,
'self_confirm' => 1,
'winner_points' => 3,
'registration_end' => today()->toDateString(),
]);
$competition->user_id = $user_id;
$competition->save();
return $competition;
}

当我在浏览器中加载测试页面时,一切正常。但是,当我测试它时,下一个断言不起作用,因为它返回 403 代码而不是 200:

$this->get('/competitions/' . $competition->id)->assertOk();

经过一些操作,我发现如果我在我的策略中使用非严格比较,它可以正常工作:

return $user->id === $competition->user_id;

你能帮我弄清楚为什么我通过create()创建的用户actingAs($user)id 和user_id字段$competition有不同的类型吗?

已编辑(添加请求的信息(: 我的竞争迁移:

Schema::create('competitions', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->string('info', 1000)->nullable();
$table->string('logo')->nullable();
$table->foreignId('user_id')->constrained();
$table->string('type');
$table->json('parameters')->nullable();
$table->unsignedTinyInteger('self_confirm');
$table->unsignedTinyInteger('tops_number');
$table->unsignedTinyInteger('winner_points');
$table->unsignedSmallInteger('round')->default(0);
$table->date('registration_end');
$table->unsignedSmallInteger('max_teams')->default(0);
$table->date('finished')->nullable();
$table->timestamps();
});

竞争模型(它包含许多仅请求和计算额外数据的方法,我只包含属性(:

protected $casts = [
'parameters' => 'object',
];
protected $fillable = [
'name',
'info',
'registration_end',
'self_confirm',
'winner_points',
'tops_number',
'type',
];

更新

我在不同的阶段测试了这些值,结果发现由于某种原因,在测试过程中,由于某种原因,注入的模型竞赛具有字符串类型的user_id属性。 在浏览器中,它是预期的整数值。

只是对您发布的代码做出一些假设,我认为,在测试之外,$competition->user_id是一个string值,而在测试中它是一个int值。您可以轻松验证此假设。

发生这种情况是因为createFakeCompetition强制$user_id的类型int,因为您在没有严格模式的情况下运行,PHP 会将传递给的字符串转换为 inteteger,但这会使比较$user->id === $competition->user_id失败。

我希望已经说清楚了。

我发现了问题。这是因为我的测试数据库类型。它使用 sqlite,它在检索结果后只有字符串值。 我刚刚从我的 phpunit 中删除了两行.xml以便使用我的主连接进行测试。

删除的行: <server name="DB_CONNECTION" value="sqlite"/> <server name="DB_DATABASE" value=":memory:"/>

最新更新