2

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!

Daniel Becker
  • 771
  • 1
  • 7
  • 25
  • You might need `static::` instead of `self::` ? – Evert Sep 26 '18 at 15:52
  • That's not the problem, I updated the question to better reflect the problem. – Daniel Becker Sep 27 '18 at 09:37
  • From the documentation [link](http://docs.mockery.io/en/latest/reference/creating_test_doubles.html#creating-test-doubles-aliasing), it seems that using a mock alias actual just creates a new stdClass object that replaces the static class you were going to use. In your case the alias mock has never had $staticArray declared on it, hence the error. Try setting $staticArray on your $mock to avoid the error you are getting. So after creating $mock try adding a line like $mock::$staticArray = ['foo', 'bar']; – grizzb Oct 09 '18 at 17:18

1 Answers1

2

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

Daniel Becker
  • 771
  • 1
  • 7
  • 25