Mocking posts and actions in WordPress Unit Tests

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.

Published
About WorkNow