Skip to content

Using --format=html while debugging unit tests with $this->json(...$args)->dump(); throws exception #36

@edvordo

Description

@edvordo

Simillar to #9 (I guess?) I'm getting an exception while running unit test and try to debug a request with the ->dump() helper, such as

class CategoryModuleTest extends TestCase
{
    public function testAdminCanAccessCategoriesModule()
    {
        $this->signIn(Admin::first());

        $this->json('GET', route('web.api.lists.categories.index'))
            ->dump()
            ->assertOk()
            ->assertJsonCount(1, 'meta.order');
    }
}
Symfony\Component\Debug\Exception\FatalThrowableError  : Argument 1 passed to Symfony\Component\VarDumper\Dumper\HtmlDumper::dump() must be an instance of Symfony\Component\VarDumper\Cloner\Data, null given, called in C:\path\to\project\vendor\symfony\var-dumper\Command\Descriptor\HtmlDescriptor.php on line 47
--
  |  
  | at C:\path\to\project\vendor\symfony\var-dumper\Dumper\HtmlDumper.php:111
  | 107\|
  | 108\|     /**
  | 109\|      * {@inheritdoc}
  | 110\|      */
  | > 111\|     public function dump(Data $data, $output = null, array $extraDisplayOptions = array())
  | 112\|     {
  | 113\|         $this->extraDisplayOptions = $extraDisplayOptions;
  | 114\|         $result = parent::dump($data, $output);
  | 115\|         $this->dumpId = 'sf-dump-'.mt_rand();
  |  
  | Exception trace:
  |  
  | 1   Symfony\Component\VarDumper\Dumper\HtmlDumper::dump([])
  | C:\path\to\project\vendor\symfony\var-dumper\Command\Descriptor\HtmlDescriptor.php:47
  |  
  | 2   Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor::describe(Object(Symfony\Component\Console\Style\SymfonyStyle), Object(Symfony\Component\VarDumper\Cloner\Data), [])
  | C:\path\to\project\vendor\beyondcode\laravel-dump-server\src\DumpServerCommand.php:81
  |  
  | 3   BeyondCode\DumpServer\DumpServerCommand::BeyondCode\DumpServer\{closure}(Object(Symfony\Component\VarDumper\Cloner\Data), [])
  | C:\path\to\project\vendor\symfony\var-dumper\Server\DumpServer.php:76
  |  
  | 4   Symfony\Component\VarDumper\Server\DumpServer::listen(Object(Closure))
  | C:\path\to\project\vendor\beyondcode\laravel-dump-server\src\DumpServerCommand.php:82
  |  
  | 5   BeyondCode\DumpServer\DumpServerCommand::handle()
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php:29
  |  
  | 6   call_user_func_array([])
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php:29
  |  
  | 7   Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php:87
  |  
  | 8   Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Object(Closure))
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php:31
  |  
  | 9   Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), [])
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Container\Container.php:572
  |  
  | 10  Illuminate\Container\Container::call()
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Console\Command.php:183
  |  
  | 11  Illuminate\Console\Command::execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
  | C:\path\to\project\vendor\symfony\console\Command\Command.php:255
  |  
  | 12  Symfony\Component\Console\Command\Command::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Console\Command.php:170
  |  
  | 13  Illuminate\Console\Command::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
  | C:\path\to\project\vendor\symfony\console\Application.php:886
  |  
  | 14  Symfony\Component\Console\Application::doRunCommand(Object(BeyondCode\DumpServer\DumpServerCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
  | C:\path\to\project\vendor\symfony\console\Application.php:262
  |  
  | 15  Symfony\Component\Console\Application::doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
  | C:\path\to\project\vendor\symfony\console\Application.php:145
  |  
  | 16  Symfony\Component\Console\Application::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Console\Application.php:89
  |  
  | 17  Illuminate\Console\Application::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
  | C:\path\to\project\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php:122
  |  
  | 18  Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
  | C:\path\to\project\artisan:37

The problem here is that $this->currentRequest->route() returns null since the $routeResolver is null and so the $controller stays set to null and HtmlDumper just doesn't like it.

I've solved my issue by adding this to the RequestContextProvider

    /**
     * Get the context.
     *
     * @return array|null
     */
    public function getContext(): ?array
    {
        if ($this->currentRequest === null) {
            return null;
        }

        $controller = null;

        if ($route = $this->currentRequest->route()) {
            $controller = $route->controller;

            if (! $controller && ! is_string($route->action['uses'])) {
                $controller = $route->action['uses'];
            }
        }

        if (app()->runningUnitTests()) {
            $controller = $this->guessPHPUnitTestController($this->currentRequest->server->get('argv'));
        }

        return [
            'uri' => $this->currentRequest->getUri(),
            'method' => $this->currentRequest->getMethod(),
            'controller' => $controller ? $this->cloner->cloneVar(class_basename($controller)) : $controller,
            'identifier' => spl_object_hash($this->currentRequest),
        ];
    }

    /**
     * Try to provide as much information to the dump as possible
     *
     * @param array $args
     *
     * @return string
     */
    private function guessPHPUnitTestController(array $args)
    {
        $controller = TestCase::class;

        var_export($args);

        if (false === in_array('--filter', $args)) {
            return $controller;
        }

        if (preg_match('/^[A-Z][a-zA-Z]+Test$/', $args[2])) {
            return $args[2];
        }

        if (preg_match('/^test[A-Z][0-9a-zA-Z]+/', $args[2])) {
            return $controller . '::' . $args[2];
        }

        return $controller;
    }

which produces
image

If this way is okay for you, I can create PR with this solution :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions