0

I'm trying to write a test of this class.



class Page
{
    private function getPage(){
        $curl = curl_init();

        curl_setopt_array($curl, array(
            CURLOPT_URL => "http://example.com/",
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "GET",
            CURLOPT_POSTFIELDS => "",
            CURLOPT_HTTPHEADER => array(
                "cache-control: no-cache"
            ),
        ));

        $response = curl_exec($curl);
        $err = curl_error($curl);

        curl_close($curl);

        return $response;

    }

    public function getTitle()
    {
        $page = $this->getPage();
        $re = '/(<title>)(.*?)(<\/title>)/m';
        preg_match_all($re, $page, $matches, PREG_SET_ORDER, 0);
        return $matches[0][2];
    }
}

And since my method getPage accesses an external resource, I need to build for it Mock

namespace Tests;
use PHPUnit\Framework\TestCase;
use App\Kernel\Page;

class PageTest extends TestCase
{
    public function testGetTitle()
    {
        $stub = $this->createMock(Page::class);
        $stub->method('getPage')
            ->willReturn('<title>Example Domain</title>');
        $this->assertSame('Example Domain', $stub->getTitle());
    }
}

When I call the test I get an error:

1) Tests\PageTest::testGetTitle Trying to configure method "getPage" which cannot be configured because it does not exist, has not been specified, is final, or is static

I watched the testing examples there they say to do so, but why the error occurs, I don’t remember - can anyone tell me how to test such a code?

  • It may be to do with it being a `private` method - https://stackoverflow.com/questions/5937845/mock-private-method-with-phpunit. – Nigel Ren Apr 05 '20 at 15:58
  • it's all clear - but how can I test it, I won’t change all the code in the tested class for the sake of the test – ff.0xff Apr 05 '20 at 16:28
  • This is a very strange code design. You have a class that deals with one specific page? It's difficult to test something like this. – El_Vanja Apr 05 '20 at 17:18
  • Have you already tried this https://stackoverflow.com/a/29636145/2270041 ? – Matteo Apr 05 '20 at 18:34

1 Answers1

0

The best way to test private methods is not to mock them or change their visibility, You should test the method that delegating the private method, in this case, you should call getTitle. or somehow trigger a method to see the side effect of that private method(You are doing it just fine). But the getTitle method as you can see it's doing nothing, it's only calling the getPage method. What I can suggest you do, is to mock curl_init which in this case it's not possible, but you can use this package to mock it. https://github.com/php-mock/php-mock-phpunit. or you can move the getPage contents to a separated class and use it as a dependency injection in your page class, then you can mock the class and expect the appropriate expectation. You can also check this example of how to unit test curl call how to unit test curl call in php

Mohammad.Kaab
  • 1,025
  • 7
  • 20