1

I'm new to Mockery. I'm trying to figure it out with the GitHub API by using a Laravel Package as a wrapper. How can I mock GitHub::repo()->show('symfony', 'demo'); without hiting the actual API? Is there something weird with Facades? I'm getting an error here:

In EvalLoader.php(34) : eval()'d code line 993:

  Cannot redeclare Mockery_0_GrahamCampbell_GitHub_Facades_GitHub::shouldReceive()  

Code:

    use Mockery;
    use Tests\TestCase;
    use GrahamCampbell\GitHub\Facades\GitHub;



    public function testExample()
    {
        $this->mockGitHubWith([
            'id' => 1,
            'name' => 'demo',
            'full_name' => 'symfony/demo',
        ]);

        $repo = GitHub::repo()->show('symfony', 'demo');

        dd($repo);
    }

    protected function mockGitHubWith($expectations)
    {
        $github = Mockery::mock(GitHub::class, $expectations);
        $github->shouldReceive('api')->andReturn($github);
        app()->instance(GitHub::class, $github);
    }

also tried:

use GrahamCampbell\GitHub\Facades\GitHub;

public function testExample()
    {
        Github::shouldReceive('api')->once()->andReturn(['id' => 1]);

        $repo = Github::repo()->show('symfony', 'demo');

        dd($repo);
    }

Returns: Mockery\Exception\BadMethodCallException: Method Mockery_0::repo() does not exist on this mock object

Just to confirm, if I remove the GitHub::shouldReceive... line, it's successful but actually hits the GitHub API.

ahinkle
  • 2,117
  • 3
  • 29
  • 58

1 Answers1

1

With the last example you are almost there. Remember you are trying to mock a two step call, first a static method and a call to an instance, therefor the mock should emulate that.

Create the repository that the repo() call will return. Using standard mockery functionality.

use Github\Api\Repo;

$repoMock = Mockery::mock(Repo::class);
$repoMock->shouldReceive('show')->with('symfony', 'demo')->once()->andReturn(['id' => 1]);

Now you can set the return type of the repo call through Laravels approach to mock facades.

Github::shouldReceive('repo')->once()->andReturn($repoMock);

When you call your code repo will return the repo mock, that expects a show call with the parameters symfony and demo.

$repo = Github::repo()->show('symfony', 'demo');
mrhn
  • 17,961
  • 4
  • 27
  • 46
  • Thank you so much. I've been looking for an answer that explains this for a week.. greatly appreciated. – ahinkle Feb 20 '20 at 16:43
  • Feel free to ping me here if you have more questions have done a lot of mocking of weird stuff :) – mrhn Feb 20 '20 at 17:46
  • Thanks! I have another weird edge case-- feel free to help here: https://stackoverflow.com/questions/60342730/laravel-how-to-mock-dependency-injection-class-methods – ahinkle Feb 21 '20 at 16:27