How to test that a model wasn't changed

In a very simple way

Joel Clermont
Joel Clermont

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);

    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,


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.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼

Level up your Laravel skills!

Each 2-minute email has real-world advice you can use.