Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kenprogrammer's avatar

PHPUnit: Mock API Call using curl

The code snippet below is an API invocation to get an Access token from my local mobile provider's payment gateway. I've written unit test and it's passing but the problem is it's invoking the live API. How do I mock the API call?

Code under Test:

<?php

    namespace Daraja\SDK;

    final class Mpesa{

        public static function getAccessToken($consumer_key,$consumer_secret)
        {
           $credentials = base64_encode($consumer_key.':'.$consumer_secret);

            $ch = curl_init('https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials');
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Authorization: Basic '.$credentials,'Content-Type: application/json'
            ]);

            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            $curl_response = curl_exec($ch);
            curl_close($ch);

            $response=json_decode($curl_response,true);

            return $response;
        }
    }
?>

The Test Class:

<?php
    namespace Daraja\SDK;

    use PHPUnit\Framework\TestCase;
    use phpmock\phpunit\PHPMock;
    use phpmock\MockBuilder;

    final class MpesaTest extends TestCase
    {
        use PHPMock;

        public function testAccessTokenCanBeGenerated()
        {
            $consumer_key='YOUR_CONSUMER_KEY';
            $consumer_secret='YOUR_CONSUMER_SECRET';

            $access_token=Mpesa::getAccessToken($consumer_key,$consumer_secret);
            $this->assertIsArray($access_token,'is an array');
            $this->assertNotEmpty($access_token,'array is not empty');
            $this->assertEquals(2,count($access_token),'array has 2 items');
            $this->assertArrayHasKey("access_token", $access_token,'array has key access_token');
            $this->assertArrayHasKey("expires_in", $access_token,'array has key expires_in');
            $this->assertNotEmpty($access_token['access_token'],'token is not empty');

        }
    }

I tried this(Mocking curl request):

 <?php
    $access_token=[
                    'access_token'=>'bY5yxSleFzHRkw9B6A7RfmV5SweK',
        'expires_in'=>'3599'
    ];

    $curl_exec = $this->getFunctionMock(__NAMESPACE__, "curl_exec");
    $curl_exec->expects($this->once())->willReturn($access_token);

    $ch = curl_init();

And also:

 <?php
    $builder = new MockBuilder();
    $builder->setNamespace(__NAMESPACE__)
            ->setName("getAccessToken")
            ->setFunction(
                function () {
                    return $access_token;
                }
            );
                        
    $mock = $builder->build();

But they didn't work. The mock build passes the test but when I remove the code under test the test still passes.

Any help will be highly appreciated.

0 likes
4 replies
eugenefvdm's avatar

@kenprogrammer I've just had to go through this and would like to know what route you went, e.g. did you end up mocking CURL?

I looked at the Stack Overflow answer too. My testing is standalone using Orchestra test bench so I have the luxury of being able to use the http client. To me to reproduce what CURL does just to mock seems too much work for now.

kenprogrammer's avatar

@eugenevdm The payment gateway I was writing a package for only provides snippets for curl. The tests hit live API but I haven't continued with development. I was thinking of creating stubs with JSON or porting to Guzzle.

Please or to participate in this conversation.