I originally wrote Laravel Tips: Making your own trait ‘hooks’ for tests last year in March, which honestly feels like a lifetime ago with everything that’s gone on. What I knew then was infinitely a lot less than now. Like all good developers I’ve been learning a ton in that time. My recent role has really pushed me to up my game in so many areas of Laravel and PHP. Working on a project that has over nearly 1000 tests running against it I’ve had to find more ways to organise that test-suite to reduce duplication where possible.
It’s with that said I’d like to reproduce my previous article and actually improve it significantly by making use of an annotation found in PHPUnit.
Previously I told you that you would need to extend the setUpTraits method in your application’s TestCase class. This was a part I always hated as it kind of made using traits a bit annoying because you still had to configure your test case. It definitely meant you could simply add your trait to a package to reuse else where without installation notes.
Turns out though you really don’t need to do this. Instead you can use the @before annotation to boot the code but this still leaves a problem for us. The TestCase class we extend for feature tests boots the application and therefor if you need to use any Facades or configure the service container or even interact with the Database you will not be able to do this from a @before method because at this point the Laravel application isn’t ready leading to some exceptions being thrown. This is why originally we needed to hook into the setUpTraits method.
There is a fix for this though.
There are two small methods that come in the Laravel application called afterApplicationCreated and beforeApplicationDestroyed both can receive acallable (a function) which will be executed at both lifecycle points.
This means we can use these methods to have exactly the same effect as we do hooking into the setup methods.
The original trait looked like this:
But now with the use of the afterApplicationCreated method we can modify this trait very quickly to work without modifying our TestCase.
Then just like previously we only need add our trait to our tests to have to automatically configure or interact with the application before each test runs.
The good thing about this is even if you were working with my old way of booting up the trait, you won’t need to change anything in the tests themselves as it will work the same as it did before.
You might as if this is worth all the effort of changing? Well for starters you can now make those traits reusable across different projects which for me is a huge bonus.
I hope this is helpful to anyone who wants to reduce the boiler plate of their tests. At the same time there is an important lesson here that you’re constantly learning as a software developer. You’ll do what was the right way when you first started doing something new. Eventually with time and some exploring of the tools you have available you will find better solutions. Don’t be afraid to use or even share that half baked idea as given enough time and input it will evolve and improve.
Thank you for reading.
I’m Peter Fox, a software developer in the UK who works with Laravel among other things. Thank you for reading my article, I’ve got several more on both medium and dev.to. If you want to know more about me, head over to https://www.peterfox.me. Also feel free to follow me @SlyFireFox on twitter for more Laravel tips and tutorials in the future.