Revision 148 | Blame | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace Illuminate\Foundation\Testing;use Carbon\CarbonImmutable;use Illuminate\Console\Application as Artisan;use Illuminate\Database\Eloquent\Model;use Illuminate\Foundation\Bootstrap\HandleExceptions;use Illuminate\Queue\Queue;use Illuminate\Support\Carbon;use Illuminate\Support\Facades\Facade;use Illuminate\Support\Facades\ParallelTesting;use Illuminate\Support\Str;use Illuminate\View\Component;use Mockery;use Mockery\Exception\InvalidCountException;use PHPUnit\Framework\TestCase as BaseTestCase;use PHPUnit\Util\Annotation\Registry;use Throwable;abstract class TestCase extends BaseTestCase{use Concerns\InteractsWithContainer,Concerns\MakesHttpRequests,Concerns\InteractsWithAuthentication,Concerns\InteractsWithConsole,Concerns\InteractsWithDatabase,Concerns\InteractsWithDeprecationHandling,Concerns\InteractsWithExceptionHandling,Concerns\InteractsWithSession,Concerns\InteractsWithTime,Concerns\InteractsWithViews,Concerns\MocksApplicationServices;/*** The Illuminate application instance.** @var \Illuminate\Foundation\Application*/protected $app;/*** The callbacks that should be run after the application is created.** @var array*/protected $afterApplicationCreatedCallbacks = [];/*** The callbacks that should be run before the application is destroyed.** @var array*/protected $beforeApplicationDestroyedCallbacks = [];/*** The exception thrown while running an application destruction callback.** @var \Throwable*/protected $callbackException;/*** Indicates if we have made it through the base setUp function.** @var bool*/protected $setUpHasRun = false;/*** Creates the application.** Needs to be implemented by subclasses.** @return \Symfony\Component\HttpKernel\HttpKernelInterface*/abstract public function createApplication();/*** Setup the test environment.** @return void*/protected function setUp(): void{static::$latestResponse = null;Facade::clearResolvedInstances();if (! $this->app) {$this->refreshApplication();ParallelTesting::callSetUpTestCaseCallbacks($this);}$this->setUpTraits();foreach ($this->afterApplicationCreatedCallbacks as $callback) {$callback();}Model::setEventDispatcher($this->app['events']);$this->setUpHasRun = true;}/*** Refresh the application instance.** @return void*/protected function refreshApplication(){$this->app = $this->createApplication();}/*** Boot the testing helper traits.** @return array*/protected function setUpTraits(){$uses = array_flip(class_uses_recursive(static::class));if (isset($uses[RefreshDatabase::class])) {$this->refreshDatabase();}if (isset($uses[DatabaseMigrations::class])) {$this->runDatabaseMigrations();}if (isset($uses[DatabaseTruncation::class])) {$this->truncateDatabaseTables();}if (isset($uses[DatabaseTransactions::class])) {$this->beginDatabaseTransaction();}if (isset($uses[WithoutMiddleware::class])) {$this->disableMiddlewareForAllTests();}if (isset($uses[WithoutEvents::class])) {$this->disableEventsForAllTests();}if (isset($uses[WithFaker::class])) {$this->setUpFaker();}foreach ($uses as $trait) {if (method_exists($this, $method = 'setUp'.class_basename($trait))) {$this->{$method}();}if (method_exists($this, $method = 'tearDown'.class_basename($trait))) {$this->beforeApplicationDestroyed(fn () => $this->{$method}());}}return $uses;}/*** Clean up the testing environment before the next test.** @return void** @throws \Mockery\Exception\InvalidCountException*/protected function tearDown(): void{if ($this->app) {$this->callBeforeApplicationDestroyedCallbacks();ParallelTesting::callTearDownTestCaseCallbacks($this);$this->app->flush();$this->app = null;}$this->setUpHasRun = false;if (property_exists($this, 'serverVariables')) {$this->serverVariables = [];}if (property_exists($this, 'defaultHeaders')) {$this->defaultHeaders = [];}if (class_exists('Mockery')) {if ($container = Mockery::getContainer()) {$this->addToAssertionCount($container->mockery_getExpectationCount());}try {Mockery::close();} catch (InvalidCountException $e) {if (! Str::contains($e->getMethodName(), ['doWrite', 'askQuestion'])) {throw $e;}}}if (class_exists(Carbon::class)) {Carbon::setTestNow();}if (class_exists(CarbonImmutable::class)) {CarbonImmutable::setTestNow();}$this->afterApplicationCreatedCallbacks = [];$this->beforeApplicationDestroyedCallbacks = [];$this->originalExceptionHandler = null;$this->originalDeprecationHandler = null;Artisan::forgetBootstrappers();Component::flushCache();Component::forgetComponentsResolver();Component::forgetFactory();Queue::createPayloadUsing(null);HandleExceptions::forgetApp();if ($this->callbackException) {throw $this->callbackException;}}/*** Clean up the testing environment before the next test case.** @return void*/public static function tearDownAfterClass(): void{static::$latestResponse = null;(function () {$this->classDocBlocks = [];$this->methodDocBlocks = [];})->call(Registry::getInstance());}/*** Register a callback to be run after the application is created.** @param callable $callback* @return void*/public function afterApplicationCreated(callable $callback){$this->afterApplicationCreatedCallbacks[] = $callback;if ($this->setUpHasRun) {$callback();}}/*** Register a callback to be run before the application is destroyed.** @param callable $callback* @return void*/protected function beforeApplicationDestroyed(callable $callback){$this->beforeApplicationDestroyedCallbacks[] = $callback;}/*** Execute the application's pre-destruction callbacks.** @return void*/protected function callBeforeApplicationDestroyedCallbacks(){foreach ($this->beforeApplicationDestroyedCallbacks as $callback) {try {$callback();} catch (Throwable $e) {if (! $this->callbackException) {$this->callbackException = $e;}}}}/*** This method is called when a test method did not execute successfully.** @param \Throwable $exception* @return void*/protected function onNotSuccessfulTest(Throwable $exception): void{parent::onNotSuccessfulTest(is_null(static::$latestResponse)? $exception: static::$latestResponse->transformNotSuccessfulException($exception));}}