Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Sam T.'s avatar

PHP Unit Error in Birdboard Series: Episode 5

I am partway through this video but when trying to run the A Project Requires An Owner feature test I get this error in the Run console in php storm:

Testing started at 7:14 AM ...
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.


Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

I tried to find something about it on the web but it seems this is not common. Does anyone have an idea of what could be causing this?

Here is my composer.json so you can see my dependencies and their versions

{
    "name": "laravel/laravel",
    "type": "project",
    "description": "The Laravel Framework.",
    "keywords": [
        "framework",
        "laravel"
    ],
    "license": "MIT",
    "require": {
        "php": "^7.4",
        "fideloper/proxy": "^4.4",
        "fruitcake/laravel-cors": "^2.0",
        "guzzlehttp/guzzle": "^7.0.1",
        "laravel/framework": "^8.12",
        "laravel/tinker": "^2.5"
    },
    "require-dev": {
        "facade/ignition": "^2.5",
        "fakerphp/faker": "^1.9.1",
        "laravel/sail": "^1.0.1",
        "mockery/mockery": "^1.4.2",
        "nunomaduro/collision": "^5.0",
        "phpunit/phpunit": "^9.5.2"
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true
    },
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "autoload": {
        "psr-4": {
            "App\": "app/",
            "Database\Factories\": "database/factories/",
            "Database\Seeders\": "database/seeders/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\": "tests/"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\Foundation\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ]
    }
}

Also note I am on Ubuntu 20.04 and locally have

PHP 8.0.2 (cli) (built: Feb  7 2021 12:22:16) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.2, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.2, Copyright (c), by Zend Technologies
0 likes
13 replies
tykus's avatar

Do you have xDebug enabled; is it up to date?

Sam T.'s avatar

I actually just installed it because I upgraded to php8 on my machine thinking that may resolve the issue.

So now I have this globally

PHP 8.0.2 (cli) (built: Feb  7 2021 12:22:16) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.2, Copyright (c) Zend Technologies
    with Xdebug v3.0.2, Copyright (c) 2002-2021, by Derick Rethans
    with Zend OPcache v8.0.2, Copyright (c), by Zend Technologies

And now when I run the test I get a new error:

Error : Xdebug has detected a possible infinite loop, and aborted your script with a stack depth of '256' frames
tykus's avatar

Interesting that it might have resulted in a memory violation rather than a max nesting error.

Likely this is an issue with your code; can you share the test code, and relevant application code?

Does this happen only in the tests, or is the application failing in the browser also?

Sam T.'s avatar

@tykus sure

ProjectTest.php

<?php

namespace Tests\Feature;

use App\Models\Project;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class ProjectsTest extends TestCase
{
    use WithFaker, RefreshDatabase;
    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function test_a_user_can_create_a_project()
    {
        //Disable exception handling
        $this->withoutExceptionHandling();

        $attributes = [
            'title' => $this->faker->sentence,
            'description' => $this->faker->paragraph,
        ];

        //Test of hitting an endpoint
        $this->post('/projects', $attributes)
            ->assertRedirect('/projects');

        //Then endpoint is it then ATTRS should be inserted into the DB
        $this->assertDatabaseHas('projects', $attributes);

        //Then should be able to see it when page is visited/viewed
        $this->get('/projects')->assertSee($attributes['title']);
    }

    public function test_a_project_requires_a_title()
    {
        $attributes = Project::factory()->raw(['title' => '']);

        /*If I make a post req to this endpoint, w/o a title
            assert that the session has errors
        */
        $this->post('/projects', $attributes)->assertSessionHasErrors('title');
    }

    public function test_a_project_requires_a_description()
    {
        $attributes = Project::factory()->raw(['description' => '']);

        /*If I make a post req to this endpoint, w/o a title
            assert that the session has errors
        */
        $this->post('/projects', $attributes)->assertSessionHasErrors('description');
    }

    public function test_a_user_can_view_a_project()
    {
        //Disable graceful exception handling
        $this->withoutExceptionHandling();

        //If we do have a project in our db
        $project = Project::factory()->create();

        //When trying to view the project assert you can see project attributes
        $this->get($project->path())
            ->assertSee($project->title)
            ->assertSee($project->description);
    }

    public function test_a_project_requires_an_owner()
    {
        $attributes = Project::factory()->raw();

        $this->post('/projects', $attributes)->assertRedirect('login');
    }
}

ProjectFactory.php

<?php

namespace Database\Factories;

use App\Models\Project;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

class ProjectFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Project::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'title' => $this->faker->sentence,
            'description' => $this->faker->paragraph,
            'owner_id' => function() {
                return Project::factory(User::class)->create()->id();
            }
        ];
    }
}

ProjectController.php

<?php

namespace App\Http\Controllers;

use App\Models\Project;
use Illuminate\Http\Request;

class ProjectsController extends Controller
{
    public function index()
    {
        return view('projects.index', ['projects' => Project::all()]);
    }

    public function store()
    {
        //Validate
        $attributes = request()->validate([
            'title' => 'required',
            'description' => 'required',
        ]);

        //Middleware validation
        $attributes['owner_id'] = auth()->id();

        //Persist
        Project::create($attributes);

        //Redirect
        return redirect('/projects', 201);

    }

    public function show(Project $project)
    {
        return view('projects.show', ['project' => $project]);
    }

}

Web.php

<?php

use App\Http\Controllers\ProjectsController;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/projects', [ProjectsController::class, 'index']);
Route::get('/projects/{project}', [ProjectsController::class, 'show']);
Route::post('/projects', [ProjectsController::class, 'store']);

I think this is all the applicable code.

Sam T.'s avatar

@tykus after configuring xdebug and running the test I am back to the original error

PHPUnit 9.5.2 by Sebastian Bergmann and contributors.


Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
tykus's avatar

Are you getting this error only whenever you run the test_a_project_requires_an_owner test; or does it also occur elsewhere in the test suite? I don't know the reason for that error, but if we can isolate the code that causes it, we might better understand the reason(s).

I noticed that the store route is not auth protected (currently); does the addition of that middleware changed the result?

The Model Factories have been changed between L7 and L8; does the test outcome if you change that test example to not use the factory, instead passing an array with title and description only?

Sam T.'s avatar

I updated the route in web.php to be:

Route::post('/projects', [ProjectsController::class, 'store'])->middleware('auth');

and I updated the method to be:

public function test_a_project_requires_an_owner()
    {
        //$attributes = Project::factory()->raw();

        $this->post('/projects', ['title' => 'test title', 'description' => 'test description'])
            ->assertRedirect('login');
    }

and now the test_a_project_requires_an_owner gives me this error:

PHPUnit 9.5.2 by Sebastian Bergmann and contributors.


Response status code [419] is not a redirect status code.
Failed asserting that false is true.

So this looks like a csrf issue.

However, if I leave the auth middleware on the store route but revert the method to use the $attributes = Project::factory()->raw(); and pass that into the post() then I go back to having the SIGSEGV error.

So it might be an issue with Project::factory() in Laravel 8... is what it is seeming like. And here is why... out of the 5 test methods I have, only the first test public function test_a_user_can_create_a_project() does NOT use the Project::factory() and is the only test, when ran, that gives me the 419 error.

But at this point I still get the Process finished with exit code 139 (interrupted by signal 11: SIGSEGV) for these test methods:

Ok so I get that error with:


public function test_a_user_can_view_a_project()
public function test_a_project_requires_a_title()
public function test_a_project_requires_a_description()
public function test_a_user_can_view_a_project()

lemmon's avatar

@samuel-torres

try changing this:

'owner_id' => function() {
        return Project::factory(User::class)->create()->id();
  }
                	

to this:

'owner_id' => User::factory(),
lemmon's avatar

also you do not have any middleware on your routes

change

Route::post('/projects', [ProjectsController::class, 'store']);

to

Route::post('/projects', [ProjectsController::class, 'store'])->middleware('auh');
lemmon's avatar

Like @tykus say's you have to isolate the problem. I say do it one test at a time following the series and do not skip anything. make sure each test is passing before you move on to the next. and be sure to run the whole suite periodically so one change does not break another test.

A couple of things have changed in laravel since that series came out to so be aware of that and adapt by using the documentation to compare.

1 like
Sam T.'s avatar

It seems this was causing the issue.

Sam T.'s avatar

It seems that I needed to:

First: Properly configure xdebug and for that I used the xdebug documentation. I copied and pasted my phpinfo() into the xdebug site to get the proper download.

Second" I changed the line as you suggested to:

'owner_id' => User::factory()

Third: On ubuntu I was missing the sqlite driver so I installed it for my version of php

sudo apt-get install php8.0-sqlite //change php versions if needed

Fourth: For the series I ensured I had these 2 lines in my phpunit.xml file

<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>

Fifth: Lastly I had to run

php artisan config:clear

All of those things together solved my problem.

2 likes

Please or to participate in this conversation.