0

I'm trying to write unit tests for a PHP Wordpress project, but I'm struggling to grasp some of the concepts when it comes to mocking up external function calls and I'm not really sure what I need to do.

Here is a very dumbed down version of the class I have created:

class Module
{
   private $title;

   public __construct($id = false)
   {
      $this->title = get_the_title($id); // core wp function
   }

   public get_title()
   {
      return $this->title;
   }

}

And I want to test it like so:

class ModuleTests extends TestCase
{
   public test_get_title_returns_title_if_id()
   {
      $module = new Module(1);
      $this->assertSame($module->get_title(), 'A Test Title'); // should equal true
   }

   public test_get_title_returns_empty_string_if_no_id()
   {
      $module = new Module();
      $this->assertSame($module->get_title(), ''); // should equal true
   }
}

Now obviously this doesn't work in isolation, because Module uses a core wordpress function in the constructor, so what is the correct method for testing in this scenario? Should I be replacing the global get_the_title() function with something that returns a hard coded value if the right arguments are passed to it? or is there some other way of doing this?

I'm trying to drag myself away from the old wordpress procedural style PHP to use some more OOP practices for the bigger projects I work on but I'm still very new to it, so if I'm doing something completely wrong feel free to give constructive critisism as well.

Also, I know that WP already has the template function the_title(), but I'm just using this as a simple example.

Thanks in advance!

3
  • 1
    You have to decide whether you want to accept that WordPress’s magic “just works” or not. You appear to be blindly passing the title through, so arguably who cares, it will work unless WordPress itself breaks, and you are still broken. For other fields, like excerpt, it might matter. If you care about the WordPress parts, WordPress has a full PHPUnit thing you can boot, including make fake in-memory posts, but it does weigh a bit. If it doesn’t really matter, the mock. Commented Nov 23, 2021 at 4:59
  • @ChrisHaas completely agree, at this point I'm just trying to get the basics and then branch out further and further as I go. Thanks for the advice! Commented Nov 24, 2021 at 22:03
  • 1
    After re-reading this, if this came off as flippant, including the "blindly passing", I apologize, that wasn't the intention, just me being literal. Back to your question, I would say "the basics" are what you are comfortable with. What Eric provided is one way to do that, and implementing full WordPress-aware PHPUnit is the other, and I really don't think there is a right or wrong. When we build WordPress plugins, we try very, very hard to have zero WordPress code in them for testing reasons, and then we build something that bridges our code with WordPress. Commented Nov 24, 2021 at 23:25

1 Answer 1

2

A common way to mock and manage such global functions is to wrap them in a class that you can inject and mock.

class WpGlobals
{
    public function get_the_title($id)
    {
        return get_the_title($id);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Ah that's nice and easy!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.