Updates see below
My controllers distinguish between ajax and other requests (using Request::ajax()
as a condition). That works quite fine but I wonder if there is a way of unit testing the controllers handling the the requests. How should a test look like?
Something like this probably but it doesn't work ...
<?php
class UsersControllerTest extends TestCase
{
public function testShowUser()
{
$userId = 1;
$response = $this->call('GET', '/users/2/routes', array(), array(), array(
'HTTP_CUSTOM' => array(
'X-Requested-With' => 'XMLHttpRequest'
)
));
}
}
Update
I kind of found a solution. Maybe. Since I am not interested in testing the proper functionality of the Request class (very likely all native classes provided by Laravel, Symfony, etc. are enough unit tested already) best way might be to mock its ajax method. Like this:
public function testShowUser()
{
$mocked = Request::shouldReceive('ajax')
->once()
->andReturn(true);
$controller = new UsersCustomRoutesController;
$controller->show(2,2);
}
Because the real Request
class and not its mocked substitute is used when using the call
method of the Testcase
class I had to instantiate the method which is called when the specified route is entered by hand. But I think that is okay because I just want to control that the expressions inside the Request::ajax()
condition work as expected with this test.
You need to prefix the actual header with HTTP_, no need to use HTTP_CUSTOM:
$server = array('HTTP_X-Requested-With' => 'XMLHttpRequest');
$this->call('get', '/ajax-route', array(), array(), $server);
Alternative syntax which looks a bit better IMO:
$this->client->setServerParameter('HTTP_X-Requested-With', 'XMLHttpRequest');
$this->call('get', '/ajax-route');
Here are some similar code examples for JSON headers (Request::isJson()
and Request::wantsJson()
):
$this->client->setServerParameter('HTTP_CONTENT_TYPE', 'application/json');
$this->call('get', '/is-json');
$this->client->setServerParameter('HTTP_ACCEPT', 'application/json');
$this->call('get', '/wants-json');
Here's a useful helper method you can put in your TestCase:
protected function prepareAjaxJsonRequest()
{
$this->client->setServerParameter('HTTP_X-Requested-With', 'XMLHttpRequest');
$this->client->setServerParameter('HTTP_CONTENT_TYPE', 'application/json');
$this->client->setServerParameter('HTTP_ACCEPT', 'application/json');
}
Here's the solution for Laravel 5.2.
$this->json('get', '/users/2/routes');
It's that simple.
Intenally, json
method applies following headers:
'CONTENT_LENGTH' => mb_strlen($content, '8bit'),
'CONTENT_TYPE' => 'application/json',
'Accept' => 'application/json',
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With