Using namespaces

This is the most elegant and evil solution you can adopt: without touching your code, you can force PHP to run your own mocked functions.
The only prerequisite is to use namespaces: if you aren't, I'm sorry but you have to fallback on one of the previous solutions.

Some background info

Before continuing, there's something you have to know about namespaces. Even if you are NOT using them, well... you are using them.
Seems weird, right?

For backward compatibility, all the native object and functions are put inside a global namespace, hence visible and accessible from everywhere.
Finally, the last thing you have to know is how PHP looks for object and functions while using namespaces: first of all it will look in the current namespace, then fallback to the global one.

Doing some cool (and evil) stuff

With the previous knowledge, we can setup some tests that will allow you to mock all the native functions. The only thing you have to do is to put your tests in the same namespace you want to test.

// file Utils\Time.php
namespace Utils;
class Timer
{
    public function getCurrentTime()
    {
        return time();
    }
}
// file TimerTest.php
namespace Utils;
class TimerTest
{
    public function testGetCurrentTime()
    {
         // actual test
    }
}
function time()
{
    // place here your custom code
	return 123;
}

If you invoke Timer::getCurentTime() what will be its return value? It will always be 123, so you can build your tests around this value.
The best thing to do is to create a good old global variable where you can store the mocked value, so you can tweak its result:

// file TimerTest.php
namespace Utils;
global $phpMock;
class TimerTest
{
    public function testGetCurrentTime()
    {
         // actual test
        $phpMock['time'] = 123;
    }
}
function time()
{
    global $phpMock;
    if(isset($phpMock['time']){
        return $phpMock['time'];
    }
    return \time();
}

Nice, isn't it?
In this way we can mock every PHP native function, just a brief example

  • All filesystem functions (even if it's better to use the VFS library for that)
  • All FTP and SFTP functions, without the need to setup a dummy server
  • cURL and WGET functions, too
  • ... and much more!

Unleash the mocking power

As a final note, I'd wish to point your attention on the function_exists method. Tweaking its result, you can test how your code acts when some module is missing. For example, what should happen when hash_aglos is not available and you have to fallback to another hashing algorithm?

Well, following the previous examples you can do something very interesting:

namespace Utils;
global $phpMock;
class UserTest
{
    public function testPassword()
    {
        global $phpMock;
        $phpMock['function_exists'] = function($function) use ($hasAlgo){
            if($function == 'hash_algo'){
                return $hasAlgo;
            }
            return '__phpunit_continue__';
        };
        // more code for your test...
    }
}
function function_exists()
{
    global $phpMock;
    if (isset($phpMock['function_exists'])){
        $result = call_user_func_array($phpMock['function_exists'], func_get_args());
        if ($result !== '__phpunit_continue__') {
            return $result;
        }
    }
    return call_user_func_array('\function_exists', func_get_args());
}

Hope this could help you on testing!