Software engineering notes

PHP Testing

Mock

Mock global function and class method

Notify.php

<?php
namespace Utility;

class Notify
{
    private $obj;

    // Parameter was passed to use as mocked object
    public function __construct($mockObj = NULL)
    {
        if ($mockObj != NULL) {
            $this->obj = $mockObj;
        } else {
            $this->obj = $this;
        }
    }

    public function doSomething($url)
    {
        $is200 = $this->obj->is200OK($url);
        $body = file_get_contents($url);
        return [$is200, $body];
    }

    public function is200OK($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_exec($ch);
        if (!curl_errno($ch)) {
            if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) {
                return true;
            }
        }
        curl_close($ch);
        return false;
    }
}

NotifyTest.php

<?php
namespace
{
    $mock = false;
}

namespace Utility
{
    // Mock global function
    function file_get_contents()
    {
        global $mock;
        if (isset($mock) && $mock === true) {
            return "file_get_contents was mocked";
        } else {
            return call_user_func_array('\file_get_contents', func_get_args());
        }
    }

    include_once 'Notify.php';
    use PHPUnit\Framework\TestCase;
    class NotifyTest extends TestCase
    {
        public function setUp()
        {
            global $mock;
            $mock = false;
        }

        public function testWithoutMock()
        {
            $dummy = new Notify();
            list($is200, $body) = $dummy->doSomething("https://google.com/");
            $this->assertTrue($is200);
        }

        public function testWithMock()
        {
            global $mock;
            $mock = true;

            // Mock class method
            $mockNotify = $this->createMock(Notify::class);
            $mockNotify->method("is200OK")->willReturn(true);

            // Inject mocked Notify class
            $dummy = new Notify($mockNotify);
            list($is200, $body) = $dummy->doSomething("https://google.com/f");
            $this->assertTrue($is200);
        }
    }
}

Ref: