Daniel Becker
Daniel Becker

Reputation: 821

Partial mocking of static class methods not working

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!

Upvotes: 2

Views: 3235

Answers (1)

Daniel Becker
Daniel Becker

Reputation: 821

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

Upvotes: 2

Related Questions