36

I am writing some tests for my controllers but one of my tests doesn't work. It's supossed to search and get the results back to the page. But it's actually redirecting to the home page. Here is my code:

use DatabaseMigrations;
protected $user;
public function setUp()
{
    parent::setUp();

    $this->seed();

    $this->user = factory(User::class)->create(['role_id' => 3]);
}

/** @test */
public function test_manage_search_user()
{
    $response = $this->followingRedirects()->actingAs($this->user)->get('/manage/users/search', [
        'choices' => 'username',
        'search' => $this->user->username,
    ]);

    $response->assertViewIs('manage.users');
    $response->assertSuccessful();
    $response->assertSee($this->user->email);
}

The URL you should get to make it work look like this:

http://localhost/manage/users/search?choices=username&search=Test

I checked again and it looks like it's not given in the parameters with the get request. How can I fix this?

2
  • Which laravel version are you using? Commented Nov 24, 2017 at 14:41
  • Laravel 5.5 am I using I could do this: $response = $this->followingRedirects()->actingAs($this->user)->get('/manage/users/search?choices=username&search='.$this->user->username.''); but that isn't as neat as I want it Commented Nov 24, 2017 at 14:51

10 Answers 10

34

I had the same issue trying to test GET Requests, you actually can't pass parameter with the $this->get('uri', [header]) but you can by using $this->call, if you check in MakesHttpRequests.php you can see that this->get() is actually using call method.

By adding an array to get method, you are changing the request headers, this is why you are not getting your parameters.

public function get($uri, array $headers = [])
{
    $server = $this->transformHeadersToServerVars($headers);

    return $this->call('GET', $uri, [], [], [], $server);
}

public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
{
    $kernel = $this->app->make(HttpKernel::class);

    $files = array_merge($files, $this->extractFilesFromDataArray($parameters));

    $symfonyRequest = SymfonyRequest::create(
        $this->prepareUrlForRequest($uri), $method, $parameters,
        $cookies, $files, array_replace($this->serverVariables, $server), $content
    );

    $response = $kernel->handle(
        $request = Request::createFromBase($symfonyRequest)
    );

    if ($this->followRedirects) {
        $response = $this->followRedirects($response);
    }

    $kernel->terminate($request, $response);

    return $this->createTestResponse($response);
}

So if you want to test a GET Request you will have to do this:

$request = $this->call('GET', '/myController', ["test"=>"test"]);

In your controller you should be able to get theses parameters like so:

public function myController(Request $request)
{
    $requestContent = $request->all();
    $parameter = $requestContent['test'];
}
Sign up to request clarification or add additional context in comments.

Comments

23

I'm using Laravel 5.X (more precisely 5.6), you can pass custom parameters using:

 $response = $this->json('GET',  '/url/endpoint',['params'=>'value']);

7 Comments

Also allow to add headers
That doesn't appear to work with Lumen 5.8.13 and \AlbertCht\Lumen\Testing\TestCase 🤷‍♂️
Worked for me with Laravel 7.19.0
This now also seems broken on Laravel 5.6, but still works on Laravel 5.5. Effectively the controllers get a null as Request object during the ->json('DELETE', 'path', ['some'=>'array']) call.
It appears if you have a function signature like destroy($id, Request $request = null) that recent that Laravel 5.6 phpunit will just goes "¯\_(ツ)_/¯ Okay I guess I don't really need to attach/inject the Request I prepared". I now removed the null expectation and swapped the position so Request is first, and everything seems to work now.
|
12

You can use the route helper to build a url with query string. in your case i would do something like this. Assuming the route name is manage.users.search

$route = route('manage.users.search', [
    'choices'=> 'username',
    'search' => $this->user->username,
]);

$response = $this->followingRedirects()
    ->actingAs($this->user)
    ->get($route);

Comments

6

In order to send parameters with GET requests.

  1. If you use the route() method then you can pass the data as the second parameter.

    $response = $this->get(route('route_name', ['key' => value]));

  2. If you using URL directly, you could use like this

    $response = $this->get('url?' . Arr::query(['key' => value]));

Do whatever you want to do with $response.

Comments

2

You could use the request helper to merge in http get parameters as such:

    /** @var \Illuminate\Http\Request $request */
    $request = request();
    $request->merge([
        'choices' => 'username',
        'search' => 'Test'
    ]);

Comments

2

The accepted answer did not work anymore on a Laravel 11.33.2 installation (API error: no-auth), but this did:

$this->get(url()->query('/path/to/api', [
    'key' => 'value',
    'search' => 'username',
]));

Here's the Laravel URL Generation docs.

1 Comment

Perhaps you could replace the "did not work for me (Laravel 11.33.2 - no-auth)" by "did not work anymore on a Laravel 11.33.2 - no-auth installation": this will look like a more general answer, and 7 years after the original post, you can be pretty confident that your new solution is not specific to your installation, but to this version of Laravel.
1

This worked for me simply pass the parameter as part of the url as follows:


$response = $this->get('api/endpoint?parameter1='.$this->dynamicParam);

Comments

1

Add a helper function:

if (!function_exists('extend_url_with_query_data')) {
    function extend_url_with_query_data(string $url, array $queryData): string
    {
        if ($queryData == []) {
            return $url;
        }

        $glue = mb_strpos($url, '?') === false ? '?' : '&';

        $queryString = http_build_query($queryData);

        return "{$url}{$glue}{$queryString}";
    }
}

Usage:

$queryData = [
    'works' => true,
];

$this->get(
    extend_url_with_query_data('/api/v1/example', $queryData)
);

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0

Late to the party, but I've been using this in my TestCase helper trait for Laravel 10.

public function getJsonWithParams($uri, $headers = [], $params = []): TestResponse
{
    return $this->getJson($uri . '?' . http_build_query($params), $headers);
}

Not amazing for discovery, but it works.

Here because I forgot I created it, and came looking for ideas.

Comments

-2

I would do it like this:

$this->actingAs($this->user);

$response = $this->get('/manage/users/search', [
    'choices' => 'username',
    'search' => $this->user->username,
]);

$response->assertViewIs('manage.users');
$response->assertSuccessful();
$response->assertSee($this->user->email);

5 Comments

My problem is that it doesn't give the parameters with it. It only works when I do this: $this->followingRedirects()->actingAs($this->user)->get('/ma‌​nage/users/search?ch‌​oices=username&searc‌​h='.$this->user->use‌​rname.''); which doens't look that neat
May i ask how are you retrieving parameters in the search method?
Currently I am able to get them with $request->get('choices')) for example
You simply need to perform assertions on what you are actually doing in that controller. Not that you receive the user email in the response.
This option is stupid if you check the parameters, this is changing headers & I don't agree on the point that this shouldn't be tested, this is a highly controversial topic about testing, and you are not making a good point here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.