On a recent project, I noticed that anytime the Carbon::setTestNow
method was used, at the end of the test, there would be an additional call to Carbon::setTestNow()
to revert to the current time.
The team thought that if they didn't do this, then the "frozen time" state would have some sort of side effect on the next test.
First of all, I love the defensive thinking here. Flaky or interdependent tests are a huge pain to deal with, so thinking about these potential issues is great to see!
But in this particular case, it's unnecessary. Why? Laravel handles it for us automatically!
The tearDown
method in the base TestCase
provided by Laravel, has these two blocks of code:
// Illuminate/Foundation/Testing/TestCase.php
if (class_exists(Carbon::class)) {
Carbon::setTestNow();
}
if (class_exists(CarbonImmutable::class)) {
CarbonImmutable::setTestNow();
}
So it's already calling it for us on every single test run. No extra work needed!
I encourage you to poke around that method to see everything else it cleans up for you.
One final thing to note: Laravel doesn't clean up everything for you. For example, if you use the Str::createUuidsUsing
method, this will NOT be cleaned up automatically.
You would want to call Str::createUuidsNormally()
yourself within the test or in the tearDown
method of the class if you're using it in multiple tests.
Tim MacDonald had a PR during the Laravel 10 cycle that would clean up all statics, but it didn't quite make the Laravel 11 release and was closed. Hopefully it gets revisited for Laravel 12!
Until then, just be aware of what you're using and what you need to clean up yourself. Laravel does a lot for you, but not everything.
Here to help,
Joel
P.S. Do you have flaky tests? Or tests that only run in a certain order? Your team does not have to live with that pain!