Search code examples
phplaraveleloquentphpunitlaravel-valet

Why Collection's toArray() method does not convert nested objects to arrays when called in a PHPUnit test?


Expected behavior:

Collections toArray() method should convert a collection to a plain array and all of the collection's nested objects that are an instance of Arrayable to an array.

Actual behavior:

toArray() method converts a collection to a plain array but the nested objects are not converted. Note that this behavior observed only when toArray() called via PHPUnit. When toArray() function called within an app or via Laravel Tinker it works as expected.

Steps To Reproduce:

Repository with a failing test
Test

Clone, install packages, run PHPUnit.

<?php

namespace Tests\Unit;

use App\User;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class CollectionToArrayTest extends TestCase
{
    use RefreshDatabase;

    /** @test */
    public function it_converts_nested_objects_that_are_an_instance_of_arrayable_to_an_array()
    {
        factory(User::class)->create();

        $users = User::get();

        // passed
        $this->assertInstanceOf(Arrayable::class, $users[0]);

        // Failed asserting that App\User Object is of type "array"
        $this->assertIsArray($users->toArray()[0]);

        // passed
        $this->assertIsArray($users->toArray()[0]->toArray());
    }
}

Observations:

  1. It've worked before, probably with previous versions of PHP and PHPUnit, however I couldn't identify the moment it has stopped.

  2. It seems that EnumeratesValues::toArray() is not called when ->toArray() is called on Collection in the provided PHPUnit test.

Laravel Version: 7.0.7
PHP Version: 7.3.15
PHPUnit Version: 8.5.2


Solution

  • Resolved the issue.

    I have Laravel Valet and PHPUnit installed globally. Valet requires tightenco/collect package that is in a conflict with Laravel Collections.

    When running PHPUnit, \Illuminate\Support\Collection gets replaced with Tightenco\Collect\Support\Collection that works differently.

    So, I've removed global PHPUnit and used local version instead.

    I created a GitHub issue