Let's say you have a job that may get fired more than once with the exact same payload. A good use case for this is webhooks. Most webhook providers guarantee at-least-once delivery, which means that while messages will never be lost, you might rarely get the same message twice.
For example, on a recent project, we were listening to a Stripe webhook that would tell us when a user had completed the onboarding process. We wanted to make sure that we only updated the user's stripe_account_onboarded
field the first time we received the webhook. If we received the webhook more than once, we would ignore it and not update the user.
Here was a simple way that we covered this logic in a test:
public function testDetailsSubmittedButAlreadyOnboarded(): void
{
$user = User::factory()->create([
'stripe_account_id' => 'stripe-id-here',
'stripe_account_onboarded' => true, // user onboarding already complete
'updated_at' => '2024-01-02 03:04:05',
]);
$webhookPayload = []; // omitted for simplicity
$job = new ProcessStripeConnectWebhook($webhookPayload);
$job->handle();
$user->refresh();
self::assertSame('2024-01-02 03:04:05', $user->updated_at->toDateTimeString());
}
The key part of this test is that we are manually setting an updated_at
value, and then asserting it hasn't changed. This is a simple way to make sure nothing changed in our User
model.
And if you pick a date in the past, you don't even have to use Carbon::setTestNow
or worry about flaky tests due to changing dates.
Here to help,
Joel
P.S. Wish you had an easy way to keep up with a wide range of security topics relevant to Laravel developers? Check out the excellent Securing Laravel newsletter by Stephen Rees-Carter.