我在 Laravel 测试套件中使用返回日期范围的模型工厂方法。例如:
class WorkSiteFactory extends Factory
{
// ... Other factory stuff....
/**
* Indicate that the Permit status is fully approved.
*/
public function withApprovedPermit(): self
{
return $this->state([
'permit_paid_at' => $this->faker->dateTimeBetween('-12 days', '-8 days'),
'permit_approved_at' => $this->faker->dateTimeBetween('-12 days', '-8 days')
]);
}
}
在测试中,我有时会使用
Carbon::setTestNow()
模拟日期,然后做出测试断言。但不幸的是 dateTimeBetween
用法不会响应模拟日期。
use App\Models\WorkSite;
use Illuminate\Support\Carbon;
use Tests\TestCase;
class SchedulerControllerTest extends TestCase
{
/** @test */
public function index_returns_correct_number_of_work_sites(): void
{
// Set the mocked "now" time
$mockNow = Carbon::parse('2024-10-01');
Carbon::setTestNow($mockNow);
// Incomplete WorkSites won't show up as available
WorkSite::factory()
->count(2)
->incomplete()
->create();
// 4 WorkSites Ready to Work
$workSites = WorkSite::factory()
->count(4)
->readyToWork()
->withApprovedPermit() // ❌ <- this should set the permit dates correctly but it doesn't adjust according to the mocked date
->create();
$response = $this
->actingAs(User::factory()->create())
->get(route('scheduler.index'))
->assertOk();
// Then asserting that the right number of
// WorkSites are returned according to the date...
// ...
}
}
我做了一些源代码挖掘,并认为也许有一种方法可以覆盖 Faker 包中的“now”,但我没有看到任何方法。
我还尝试将返回值包装在
Carbon::instance()
和 Carbon::parse()
中,但都不起作用。
我确信有一种奇怪的方法可以编写一个方法,该方法获取 Faker 的结果并根据
Carbon::now()
时间进行调整,但这似乎是错误的解决方案。
提前致谢!
Faker 使用 PHP 的 DateTime 类,并且不以任何方式使用 Carbon(它扩展了 DateTime)。
由于模型工厂仅在测试套件中使用,因此您可以向 withApprovedPermit() 添加一个参数,您可以在其中提供 DateTime 对象。
或者您可以在创建后手动设置对象的日期(前提是您有所需的设置器)