Skip to content

Bootstrap the application when tests refresh it#423

Closed
anabeto93 wants to merge 2 commits into
hypervel:0.4from
anabeto93:fix/bootstrap-application-for-tests
Closed

Bootstrap the application when tests refresh it#423
anabeto93 wants to merge 2 commits into
hypervel:0.4from
anabeto93:fix/bootstrap-application-for-tests

Conversation

@anabeto93

@anabeto93 anabeto93 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

The default ExampleTest of a freshly scaffolded 0.4 application fails out of the box:

RuntimeException: A facade root has not been set.
  src/support/src/Facades/Facade.php:349
  src/foundation/src/Testing/Concerns/InteractsWithTestCaseLifecycle.php:71
  src/foundation/src/Testing/TestCase.php:61

refreshApplication() only creates the application — the bootstrappers (LoadConfiguration, RegisterFacades, RegisterProviders, BootProviders, …) run on the HTTP and console boot paths but never on the test path, so the facade root is never bound and the first facade call in setUp() throws. The components suite doesn't catch this because unit tests don't boot a container and Testbench has its own bootstrap path; only real applications extend Foundation\Testing\TestCase directly.

This bootstraps the freshly-created application in refreshApplication(). HandleExceptions is deliberately omitted so PHPUnit reports failures instead of the app's Swoole error handler.

Verified on a fresh skeleton app:

vendor/bin/phpunit tests/Feature/
OK (2 tests, 3 assertions)

Summary by CodeRabbit

  • Bug Fixes

    • Improved test startup reliability by ensuring the application is properly bootstrapped before tests run.
    • Test runs now surface failures more directly when the app isn’t fully initialized, reducing flaky “incomplete setup” failures.
  • Improvements

    • Centralized the default application bootstrap sequence and applied it consistently to both HTTP and console kernels for more predictable startup behavior.

refreshApplication() only created the application. The bootstrappers
(LoadEnvironmentVariables, LoadConfiguration, RegisterFacades,
RegisterProviders, GenerateProxies, BootProviders) only run on the HTTP
and console boot paths, so on the test path the facade root was never
bound and the first facade call in setUp() failed with "A facade root
has not been set" — the default ExampleTest of a fresh application
fails out of the box.

Bootstrap the freshly-created application in refreshApplication().
HandleExceptions is deliberately omitted so PHPUnit reports failures
instead of the Swoole error handler.
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d5a105b-47e3-444a-af1b-d174cce8de26

📥 Commits

Reviewing files that changed from the base of the PR and between 9baec67 and b141d53.

📒 Files selected for processing (4)
  • src/foundation/src/Application.php
  • src/foundation/src/Console/Kernel.php
  • src/foundation/src/Http/Kernel.php
  • src/foundation/src/Testing/TestCase.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/foundation/src/Testing/TestCase.php

📝 Walkthrough

Walkthrough

A shared default bootstrapper list was added to Application, both kernels now use it, and TestCase::refreshApplication() bootstraps fresh apps with that sequence while omitting HandleExceptions.

Changes

Shared bootstrap sequence

Layer / File(s) Summary
Default bootstrapper constant
src/foundation/src/Application.php
Application defines a public DEFAULT_BOOTSTRAPPERS constant with the framework bootstrap class sequence and typing annotations.
Kernel bootstrapper defaults
src/foundation/src/Console/Kernel.php, src/foundation/src/Http/Kernel.php
Both kernels now initialize their bootstrapper lists from Application::DEFAULT_BOOTSTRAPPERS instead of inline arrays.
Test application refresh bootstrapping
src/foundation/src/Testing/TestCase.php
refreshApplication() conditionally bootstraps a fresh app with the shared default bootstrapper list minus HandleExceptions.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: bootstrapping the application during test refresh.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/foundation/src/Testing/TestCase.php (1)

76-85: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Share the bootstrapper list with the app kernels.

src/foundation/src/Testing/TestCase.php duplicates the same bootstrapper sequence already defined in src/foundation/src/Http/Kernel.php and src/foundation/src/Console/Kernel.php, with only HandleExceptions intentionally omitted here. A shared bootstrapper source or helper would keep the test path from drifting when the app boot sequence changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/foundation/src/Testing/TestCase.php` around lines 76 - 85, The
bootstrapper sequence in TestCase::createApplication is duplicated from the app
kernels and can drift over time; extract the shared bootstrapper list into a
common source used by Http\Kernel and Console\Kernel, then reuse it in
Testing\TestCase while keeping HandleExceptions excluded there. Update the
bootstrapper setup so all three paths reference the same shared sequence rather
than hardcoding the list in each place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/foundation/src/Testing/TestCase.php`:
- Around line 76-85: The bootstrapper sequence in TestCase::createApplication is
duplicated from the app kernels and can drift over time; extract the shared
bootstrapper list into a common source used by Http\Kernel and Console\Kernel,
then reuse it in Testing\TestCase while keeping HandleExceptions excluded there.
Update the bootstrapper setup so all three paths reference the same shared
sequence rather than hardcoding the list in each place.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: be40302a-049e-42e1-bc07-edc6a6600fc0

📥 Commits

Reviewing files that changed from the base of the PR and between b87676c and 9baec67.

📒 Files selected for processing (1)
  • src/foundation/src/Testing/TestCase.php

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a RuntimeException: A facade root has not been set error that caused the default ExampleTest of a freshly-scaffolded 0.4 application to fail immediately. The root cause was that bootstrappers (RegisterFacades, RegisterProviders, BootProviders, etc.) were only wired into the HTTP and console boot paths, never into the test path.

  • Extracts the shared bootstrap sequence into Application::DEFAULT_BOOTSTRAPPERS, replacing the duplicated inline arrays in Http/Kernel.php and Console/Kernel.php.
  • Calls bootstrapWith() in refreshApplication() with all default bootstrappers except HandleExceptions, so PHPUnit — not the Swoole error handler — reports test failures; the hasBeenBootstrapped() guard prevents double-bootstrapping if the app was already initialised by createApplication().

Confidence Score: 5/5

Safe to merge; the bootstrapping logic is correct and well-guarded, and the one nit is purely stylistic.

The fix is straightforward: the hasBeenBootstrapped() guard prevents accidental double-bootstrapping, both Http and Console kernels already use the same guard in their own bootstrap() methods so the shared constant cannot cause drift, and deliberately excluding HandleExceptions in the test path is correct and well-explained.

No files require special attention beyond the single FQCN style nit in src/foundation/src/Testing/TestCase.php.

Important Files Changed

Filename Overview
src/foundation/src/Application.php Adds DEFAULT_BOOTSTRAPPERS public constant to centralise the shared bootstrap sequence; FQCNs in the array literal are acceptable under the config-style list exception.
src/foundation/src/Http/Kernel.php Replaces inline bootstrapper array with Application::DEFAULT_BOOTSTRAPPERS; pure deduplication, no behaviour change.
src/foundation/src/Console/Kernel.php Same deduplication as Http/Kernel; BootProviders import is still used in bootstrapWithoutBootingProviders(), so no orphaned import.
src/foundation/src/Testing/TestCase.php Adds bootstrap call in refreshApplication() excluding HandleExceptions; logic is sound but HandleExceptions is referenced as a FQCN without a use import.

Reviews (2): Last reviewed commit: "Share the default bootstrapper sequence ..." | Re-trigger Greptile

The HTTP kernel, the console kernel, and the test path each hardcoded
the same bootstrapper list. Move it to
Application::DEFAULT_BOOTSTRAPPERS so the three paths cannot drift;
the test path keeps excluding HandleExceptions.
@anabeto93

Copy link
Copy Markdown
Contributor Author

Addressed in b141d53 — the sequence now lives in Application::DEFAULT_BOOTSTRAPPERS, both kernels initialize their $bootstrappers from it, and the test path reuses it minus HandleExceptions.

@binaryfire

Copy link
Copy Markdown
Collaborator

Thanks for the PR. This bug needed some bigger refactoring. Fixed in #426

@binaryfire binaryfire closed this Jul 8, 2026
@anabeto93 anabeto93 deleted the fix/bootstrap-application-for-tests branch July 8, 2026 11:50
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

Successfully merging this pull request may close these issues.

2 participants