Summer Sale! All accounts are 50% off this week.

jrdavidson's avatar

Mockery Testing Iterations of a Class

What I'm trying to figure out is how to properly test the AddCompetitorsToGameAction . I have the AddPlayersToGameAction` tested individually. What will be helpful to know here is the reason for the different integer keys of the collection is that it is dependent upon the type of game type it is.

If a game has two sides to the game then it would have two nested arrays if it was more than 2 it would have that many number of sides to the game.

Anyone who has experience with Mockery please assist.

test('it adds players to a game', function () {
    $game = Game::factory()->create();
    [$playerA, $playerB] = Player::factory()->count(2)->create();
    $competitors = collect([
        0 => [
            'players' => collect([$playerA]),
        ],
        1 => [
            'players' => collect([$playerB]),
        ],
    ]);

    AddPlayersToGameAction::shouldRun()
        ->with($match, Arr::get($competitors, 'players'), $competitors->count())
        ->times(count(Arr::get($competitors, 'players')));

    AddCompetitorsToGameAction::run($game, $competitors);
});

AddCompetitorsToGameAction

public function handle(Game $game, Collection $competitors): void
    {
        foreach ($competitors as $sideNumber => $sideCompetitors) {
            if (Arr::exists($sideCompetitors, 'players')) {
                AddPlayersToMatchAction::run($game, Arr::get($sideCompetitors, 'players'), $sideNumber);
            }

            if (Arr::exists($sideCompetitors, 'coaches')) {
                AddCoachesToGameAction::run($game, Arr::get($sideCompetitors, 'coaches'), $sideNumber);
            }
        }
    }
0 likes
1 reply
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

To properly test the AddCompetitorsToGameAction class, you can use Mockery to mock the AddPlayersToMatchAction and AddCoachesToGameAction classes. Here's an example test case:

use Mockery\MockInterface;

class AddCompetitorsToGameActionTest extends TestCase
{
    public function test_it_handles_competitors()
    {
        $game = Game::factory()->create();
        [$playerA, $playerB] = Player::factory()->count(2)->create();
        $competitors = collect([
            0 => [
                'players' => collect([$playerA]),
            ],
            1 => [
                'players' => collect([$playerB]),
            ],
        ]);

        $addPlayersMock = $this->mock(AddPlayersToMatchAction::class, function (MockInterface $mock) use ($game, $competitors) {
            $mock->shouldReceive('run')
                ->times(count($competitors))
                ->with($game, Mockery::any(), Mockery::any());
        });

        $addCoachesMock = $this->mock(AddCoachesToGameAction::class, function (MockInterface $mock) use ($game, $competitors) {
            $mock->shouldReceive('run')
                ->times(count($competitors))
                ->with($game, Mockery::any(), Mockery::any());
        });

        AddCompetitorsToGameAction::run($game, $competitors);

        $addPlayersMock->shouldHaveReceived('run');
        $addCoachesMock->shouldNotHaveReceived('run');
    }
}

In this test case, we're mocking the AddPlayersToMatchAction and AddCoachesToGameAction classes using Mockery. We're then passing these mocks to the AddCompetitorsToGameAction class and asserting that the run method is called on the AddPlayersToMatchAction mock the correct number of times.

We're also asserting that the run method is not called on the AddCoachesToGameAction mock, since there are no coaches in the $competitors collection.

Note that we're using the shouldReceive method to set expectations on the mocked methods, and the shouldHaveReceived and shouldNotHaveReceived methods to assert that the methods were called or not called, respectively.

Please or to participate in this conversation.