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

tzookb's avatar

I need to mock a php function

have my class that inside it's method it uses php function:

shell_exec($cmd)

now I want to override it's implementations so I could mock and test my class, somebody here done something like this?

0 likes
3 replies
eszterczotter's avatar
Level 31

In phpunit with Mockery:

I had the same problem a few months ago. This is what worked for me:

You could namespace your test with the namespace of the class under test. Then, before the test class, create the function in that namespace, like this:

<?php namespace The\Same\Like\The\Class\Under\Test

use \Mockery;

function shell_exec($cmd)
{
  return YourTest::$functions->shell_exec($cmd);
}

class YourTest extends \PHPUnit_Framework_TestCase {
  public static $functions;

  public function setUp()
  {
    self::$functions = Mockery::mock();
  }
}

Now, when you're testing your class, and want to mock the function, you could write it like this:

    self::$functions->shouldReceive('shell_exec')->with($cmd)->once();

Or in whatever way you want to mock it.

In phpspec:

This is exactly why I didn't use phpspec when I had this problem.

I think (but not sure) that with a phpspec approach in mind, you would wrap the shell command in a class, like this:

class Shell{
  public function exec($cmd)
  {
    return shell_exec($cmd);
  }
}

I guess, there's no need to test this class, since it's just a wrapper. Then, you would use this class instead of the function in your other classes, and when it comes to mocking, you could mock this class.

2 likes
tzookb's avatar

thanks just found this exact answer as well, great!

malkusch's avatar

Instead of defining the namespaced function shell_exec() yourself you could do that with php-mock-phpunit . This has the advantage that you didn't create a side effect with your test, as the mock will be destroyed after a test:

<?php

namespace foo;

use phpmock\phpunit\PHPMock;

class ShellExecTest extends \PHPUnit_Framework_TestCase
{

    use PHPMock;
    
    public function testShellExec()
    {
        $exec = $this->getFunctionMock(__NAMESPACE__, "shell_exec");
        $exec->expects($this->once())->with("foo")->willReturn("bar");

        $this->assertEquals("bar", shell_exec("foo"));
    }
}

There are also php-mock integrations with other dialects:

1 like

Please or to participate in this conversation.