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?
What’s WordPress got to do with this?
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.
Wait. What are mocks?
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.
Great. Let’s get to the point.
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 setUp()
and tearDown()
PhpSpec provides similar methods called let()
and letGo()
. Those methods should be written as so:
class TodoSpec extends ObjectBehavior {
public function let() {
\WP_Mock::setUp();
}
public function letGo() {
\WP_Mock::tearDown();
}
}
With that in place we are free to use WP_Mock 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 wp_insert_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!