Partial mocking of static class methods not working

2.9k Views Asked by At

I am trying to mock a single static method on a class. However, if I call the mocked method, the class variables aren't found anymore. It seems like the entire class is mocked and makePartial() is ignored.

I created an error case in a blank laravel project. Here's the relevant code:

AnotherController:

namespace App\Http\Controllers;

class AnotherController extends Controller
{
    public function coolMethod()
    {
        logger(StaticController::$staticArray);
        logger(StaticController::staticMethod('arg1'));
    }
}

StaticController

namespace App\Http\Controllers;

class StaticController extends Controller
{
    public static $staticArray = [
        'foo',
        'bar'
    ];

    public static function staticMethod($arg1, $arg2 = [])
    {
        logger("The real static method");
        logger(self::$staticArray);
    }
}

Example Test

namespace Tests\Feature;

use App\Http\Controllers\AnotherController;
use App\Http\Controllers\StaticController;

use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testStaticMock()
    {
        $mock = \Mockery::mock('alias:App\Http\Controllers\StaticController');
        $mock
            ->makePartial()
            ->shouldReceive('staticMethod')
            ->withAnyArgs()
            ->andReturn("I'm the mocked return");

        $anotherController = new AnotherController();
        logger($anotherController->coolMethod());

        logger(StaticController::staticMethod());
    }
}

Output:

[16:01:24] user@shell [~/Development/Code/Laravel] $ vendor/phpunit/phpunit/phpunit -v
PHPUnit 6.5.13 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.0.14 with Xdebug 2.6.0
Configuration: /Users/.../Development/Code/Laravel/phpunit.xml

E                                                                   1 / 1 (100%)

Time: 183 ms, Memory: 12.00MB

There was 1 error:

1) Tests\Feature\ExampleTest::testStaticMock
Error: Access to undeclared static property: App\Http\Controllers\StaticController::$staticArray

/Users/.../Development/Code/Laravel/app/Http/Controllers/AnotherController.php:9
/Users/.../Development/Code/Laravel/tests/Feature/ExampleTest.php:22

ERRORS!
Tests: 1, Assertions: 1, Errors: 1.

As you can see, $staticArray can't be found anymore even though it's defined on the original class.

Any help is much appreciated!

1

There are 1 best solutions below

0
Daniel Becker On BEST ANSWER

As it turns out, it is not possible to use makePartial() with alias mocking. That's because the class is replaced entirely:

Prefixing the valid name of a class (which is NOT currently loaded) with “alias:”
will generate an “alias mock”. Alias mocks create a class alias with the given classname
to stdClass and are generally used to enable the mocking of public static methods.
Expectations set on the new mock object which refer to static methods will be used
by all static calls to this class.

The documentation can be found here