Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot partially mock an alias #1195

Open
NemoFlopsington opened this issue Oct 21, 2022 · 1 comment
Open

Cannot partially mock an alias #1195

NemoFlopsington opened this issue Oct 21, 2022 · 1 comment

Comments

@NemoFlopsington
Copy link

NemoFlopsington commented Oct 21, 2022

My static class

class StaticClass
{
    public static function foo()
    {
        return "foo";
    }

    public static function bar()
    {
        return "bar";
    }
}

My Test

/**
     * Test mocking static methods
     *
     * @runTestsInSeparateProcesses
     * @preserveGlobalState disabled
     * @return void
     */
    public function testMockStaticMethods()
    {
        $staticClassMock = Mockery::mock('alias:' . StaticClass::class)->makePartial();
        $staticClassMock->shouldReceive('foo')->andReturn("mockedFoo");

        //passed
        self::assertEquals("mockedFoo", StaticClass::foo());
        //throws an error
        self::assertEquals("bar", StaticClass::bar());
    }

Currently this throws an error saying "Static method App\Models\StaticClass::bar() does not exist on this mock object"
I believe partial mocking on aliased classes is not currently supported. Is this due to a design limitation, or has there not been any resources to implement this feature? My main use case for this feature would be mocking Eloquent models. I'd like to mock MyModel::find() while keeping functions like MyModel::make.

@ghostwriter
Copy link
Member

Hey @NemoFlopsington,

Unfortunately, there had not been enough resources to implement this and a few other features. Hoping to fix that. I was able to reproduce the test case you provided.

For mocking Eloquent models

  • Making a Stub model specifically for testing
use App\Models\User;
use Illuminate\Database\Eloquent\Model;

class MyModel extends User
{
    public static function find(mixed $id, iterable $columns = ['*']): MockInterface
    {
        $mock = \mock(Collection::class);
        $mock->shouldReceive('find')->once()->with($id, $columns)->andReturn([]);
        return $mock;
    }
}
  • and not using alias: both worked.
use App\Models\User;
use Mockery;
use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    /**
     * Test mocking static methods
     *
     * @runTestsInSeparateProcesses
     * @preserveGlobalState disabled
     * @return void
     */
    public function testMockStaticMethods(): void
    {
        $staticClassMock = Mockery::mock(User::class)->makePartial();
        $staticClassMock->shouldReceive('foo')->andReturn('mockedFoo');
        // passes
        self::assertEquals('mockedFoo', $staticClassMock::foo());
        // passes
        self::assertEquals('bar', $staticClassMock::bar());
    }
}

// User model
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    public static function foo(): string
    {
        return 'foo';
    }

    public static function bar(): string
    {
        return 'bar';
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants