Over the last few weeks I’ve begun a push to increase our test coverage in OptinMonster with PhpSpec. Doing so will allow the team to release features with greater confidence and reduce bugs throughout the codebase. As tests were being written I quickly ran into issues mocking WordPress functions. Yep! OptinMonster is written on top of WordPress!
After trying out a couple of different testing frameworks we’ve settled on PhpSpec as our framework of choice. You and I could argue over the merits of our decision but it comes down to this: Compared to the dominant PHPUnit, PhpSpec seems to be more conducive to onboarding new or junior developers and the tests read more like plain English. Which of the tests below read easier for you?
With frameworks architected in an object-oriented manner from the very beginning (i.e. Laravel, Symfony) mocking dependencies is a trivial matter. Those frameworks avoid placing functions in the global scope and when they do those functions are usually wrappers for encapsulated functionality. WordPress is a different story. Now, this isn’t an article about the pros & cons of WordPress. There’s been more than enough written on that subject. So, the point is mocking most of WordPress’ functionality which presents an interesting challenge. Thankfully the ever-hiring team at 10up has created a mocking framework specifically for WordPress called WP_Mock. This creates an API that makes WordPress-related mocks quick and painless.
In unit testing mocks are basically copies of dependencies within your code. The purpose is to isolate the behavior of the class/methods you are testing from those dependencies. The hope is those dependencies already have good unit tests behind them so you can easily fake their behavior.
With all of the explanations out of the way I can finally show you how to get WP_Mock working with PhpSpec. The WP_Mock documentation shows how to easily get up and running with PHPUnit and luckily the ideas translate over to PhpSpec really well. Instead of using
tearDown() PhpSpec provides similar methods called
letGo(). Those methods should be written as so:
With that in place we are free to use WPMock as we would in PHPUnit. Here’s a simple test for our Todo class. We need to make sure that when we call our
save() method on the Todo that the proper WordPress function is called with specific arguments so that it can be saved to the database. Since we are mocking `wpinsert_post()` the database won’t actually be changed which greatly simplifies testing and helps us focus only on the code we are writing.
That’s it! If you have any questions about unit testing your own WordPress plugins let me know in the comments!