Simulate HTTP and parse route request parameters in Laravel test sheet

I am trying to create unit tests to test some specific classes. I use app()->make()to create instances for testing. So actually HTTP requests are not required.

However, some of the tested functions need information from the routing parameters, so they will make calls, for example. request()->route()->parameter('info'), and this throws an exception:

Call function member function () at zero.

I played a lot and tried something like:

request()->attributes = new \Symfony\Component\HttpFoundation\ParameterBag(['info' => 5]);  

request()->route(['info' => 5]);  

request()->initialize([], [], ['info' => 5], [], [], [], null);

but none of them worked ...

How can I manually initialize the router and supply some routing parameters to it? Or just make it request()->route()->parameter()available?

Update

@Loek: You didn't understand me. Basically, I do:

class SomeTest extends TestCase
{
    public function test_info()
    {
        $info = request()->route()->parameter('info');
        $this->assertEquals($info, 'hello_world');
    }
}

"". request()->route()->parameter() . . , .

+4
2

, . .

. !

, Laravel Illuminate\Http\Request Symfony\Component\HttpFoundation\Request. upstream URI setRequestUri(). . .

, . :

<?php

use Illuminate\Http\Request;

class ExampleTest extends TestCase
{
    public function testBasicExample()
    {
        $request = new Request([], [], ['info' => 5]);

        dd($request->route()->parameter('info'));
    }
}

, :

: ()

Route

? route() null?

, ; getRouteResolver(). getRouteResolver() , route() , $route null. , ... .

HTTP- Laravel , . , , . , .

<?php

use Illuminate\Http\Request;
use Illuminate\Routing\Route;

class ExampleTest extends TestCase
{
    public function testBasicExample()
    {
        $request = new Request([], [], ['info' => 5]);

        $request->setRouteResolver(function () use ($request) {
            return (new Route('GET', 'testing/{info}', []))->bind($request);
        });

        dd($request->route()->parameter('info'));
    }
}

. Route Laravel RouteCollection .

, , . . phpunit, null ! dd($request->route()), , info, parameters :

Illuminate\Routing\Route {#250
  #uri: "testing/{info}"
  #methods: array:2 [
    0 => "GET"
    1 => "HEAD"
  ]
  #action: array:1 [
    "uses" => null
  ]
  #controller: null
  #defaults: []
  #wheres: []
  #parameters: [] <===================== HERE
  #parameterNames: array:1 [
    0 => "info"
  ]
  #compiled: Symfony\Component\Routing\CompiledRoute {#252
    -variables: array:1 [
      0 => "info"
    ]
    -tokens: array:2 [
      0 => array:4 [
        0 => "variable"
        1 => "/"
        2 => "[^/]++"
        3 => "info"
      ]
      1 => array:2 [
        0 => "text"
        1 => "/testing"
      ]
    ]
    -staticPrefix: "/testing"
    -regex: "#^/testing/(?P<info>[^/]++)$#s"
    -pathVariables: array:1 [
      0 => "info"
    ]
    -hostVariables: []
    -hostRegex: null
    -hostTokens: []
  }
  #router: null
  #container: null
}

['info' => 5] Request . Route , $parameters.

, $parameters bindParameters(), , , bindPathParameters(), ( ).

Symfony Symfony\Component\Routing\CompiledRoute ( ) , . , ( ).

/**
 * Get the parameter matches for the path portion of the URI.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
protected function bindPathParameters(Request $request)
{
    preg_match($this->compiled->getRegex(), '/'.$request->decodedPath(), $matches);
    return $matches;
}

, , $request->decodedPath() /, . , , .

URI

decodedPath() Request, , , , prepareRequestUri() Symfony\Component\HttpFoundation\Request. , , .

URI , HTTP-. X_ORIGINAL_URL, X_REWRITE_URL, , , REQUEST_URI. spoof URI HTTP-. .

<?php

use Illuminate\Http\Request;
use Illuminate\Routing\Route;

class ExampleTest extends TestCase
{
    public function testBasicExample()
    {
        $request = new Request([], [], [], [], [], ['REQUEST_URI' => 'testing/5']);

        $request->setRouteResolver(function () use ($request) {
            return (new Route('GET', 'testing/{info}', []))->bind($request);
        });

        dd($request->route()->parameter('info'));
    }
}

, 5; info.

Cleanup

, simulateRequest() SimulatesRequests, .

Mocking

URI , , URI . - :

<?php

use Illuminate\Http\Request;
use Illuminate\Routing\Route;

class ExampleTest extends TestCase
{

    public function testBasicExample()
    {
        $requestMock = Mockery::mock(Request::class)
            ->makePartial()
            ->shouldReceive('path')
            ->once()
            ->andReturn('testing/5');

        app()->instance('request', $requestMock->getMock());

        $request = request();

        $request->setRouteResolver(function () use ($request) {
            return (new Route('GET', 'testing/{info}', []))->bind($request);
        });

        dd($request->route()->parameter('info'));
    }
}

5.

+7

phpunit Laravel, TestCase visit().

( , , ), .

class UserTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        // This is readable but there a lot of under-the-hood magic
        $this->visit('/home')
             ->see('Welcome')
             ->seePageIs('/home');

        // You can still be explicit and use phpunit functions
        $this->assertTrue(true);
    }
}
0

Source: https://habr.com/ru/post/1665716/


All Articles