stub a single function – no class involved – php

The first function you see in this wp source code is what I want to stub out, according to the phpunit docs I would stub the class, followed by the method and what that method would return. Then I could call the class and expect the method to be called once.

How ever in the following function – which i have in a class:

Read More
public function checked($value, $option, $key) {
    $options = get_option($option);

    if (isset($options[$key]) && $options[$key] == $value) {
        return $this->checked =  'checked';
    }
}

you can see I call get_option() I need to stub that function to return a specific array back, how can I do that in php?

Related posts

Leave a Reply

3 comments

  1. You cannot stub functions.

    The reason it works with classes is because PHPUnit creates PHP source code on the fly declaring a mock class that extends the original, overwriting the function to be stubbed. And it cannot work with functions declared as final.

    However, there is one situation that allows to even stub functions: Using namespaces.

    Calling a function will first try to call a function of that name in the current namespace. If there is none, the global namespace is used. That way, even inside a namespace, you can directly call PHP functions like strpos() without having to worry about prefixing them all with a backslash.

    Now see this as an example:

    namespace Stub;
    
    function strpos($foo, $bar) {
        return "The return value is stubbed";
    }
    
    # This will not call the PHP function
    echo strpos("string", "i");
    

    So if you put your test into a namespace, and define the function in the same namespace, a call to that function would be intercepted.

    Now the only annoyance is that the code in the class you want to test has to be in the same namespace (or the other way round – the test and stub function have to be in the namespace of the class you want to test) – if it is not, you cannot add the function to that namespace. Additionally, you can only add the function ONCE – you should have an idea how to make the function behave like a mock, perhaps having a global variable containing the configured mock object that is used to check calls and provide return values.

    However, this will all get messy sooner or later. Global functions cannot really be mocked/stubbed in a clean way in PHP.

  2. Indeed, WordPress uses functions a lot and they’re hard to stub in a clean way.

    However, what you can do is wrap the function in a method like this:

    public function get_option($option) {
        return get_option($option);
    }
    
    public function checked($value, $option, $key) {
        $options = $this->get_option($option);
    
        if (isset($options[$key]) && $options[$key] == $value) {
            return $this->checked =  'checked';
        }
    }
    

    Now you can easily mock the get_option method!