Mocking posts and actions in WordPress Unit Tests

Despite a lack of rich documentation, WordPress classes exist that provide mocking functionality. In simple cases, they obviate the need for separate libraries.

Scenario

You wrote a plugin that hooks post updates and fires a custom action in response. How would you test if that custom action was fired?

For setup, I assume the default scaffolding given by the WP CLI for testing.

Arrange

To start, we need a mock post to update. We’ll also need a mock action that will tell us if it was ever fired.

WordPress includes a set of factories for testing. These are available when using the WP_UnitTestCase class.

Here’s an example that creates a post object:


class ExampleTest extends WP_UnitTestCase {

function testExample() {
$post = $this->factory->post->create_and_get([
"post_title" => "Test Post"
]);
}

}

WordPress also includes a MockAction class that allows us to create action mocks. It lives in the utils.php file.

With that class, we can create a mock action and attach it to our custom hook:


class ExampleTest extends WP_UnitTestCase {

function testExample() {
$post = $this->factory->post->create_and_get([
"post_title" => "Test Post"
]);

// Create mock action
$action = new MockAction();

// Attach the action to our custom hook
add_action('my_custom_hook', [&$action, 'action']);

}

}

Act & Assert

To update the post, we’ll use the wp_update_post function. In this example, we’ll assume our imaginary plugin listens for the save_post action and fires the custom my_custom_hook action in response.


class ExampleTest extends WP_UnitTestCase {

function testExample() {
$post = $this->factory->post->create_and_get([
"post_title" => "Test Post"
]);

$action = new MockAction();

add_action('my_custom_hook', [&$action, 'action']);

wp_update_post([
"ID" => $post->ID,
"post_title" => "Updated title"
]);

// Check that the action was called at least once
$this->assertGreaterThan(0, $action->get_call_count());
}

}

With the assertion at the end, we’re done. This test will check if calling updating a post has the side effect of firing the my_custom_hook action.

For more information, check out:

Finally, more functionality exists in the WordPress core testing files, so I encourage the reader to comb through those files.