Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing laravel controllers with JSON request body

I am trying to write a phpunit test for a Laravel controller which expects post requests with a body in JSON format.

A simplified version of the controller:

class Account_Controller extends Base_Controller
{
    public $restful = true;

    public function post_login()
    {
        $credentials = Input::json();
        return json_encode(array(
            'email' => $credentials->email,
            'session' => 'random_session_key'
        ));
    }
}

Currently I have a test method which is correctly sending the data as urlencoded form data, but I cannot work out how to send the data as JSON.

My test method (I used the github gist here when writing the test)

class AccountControllerTest extends PHPUnit_Framework_TestCase {
    public function testLogin()
    {
        $post_data = array(
            'email' => '[email protected]',
            'password' => 'example_password'
        );
        Request::foundation()->server->set('REQUEST_METHOD', 'POST');
        Request::foundation()->request->add($post_data);
        $response = Controller::call('account@login', $post_data);
        //check the $response
    }
}

I am using angularjs on the frontend and by default, requests sent to the server are in JSON format. I would prefer not to change this to send a urlencoded form.

Does anyone know how I could write a test method which provides the controller with a JSON encoded body?

like image 488
Reidsy Avatar asked Jan 05 '13 12:01

Reidsy


3 Answers

In Laravel 5, the call() method has changed:

$this->call(
    'PUT', 
    $url, 
    [], 
    [], 
    [], 
    ['CONTENT_TYPE' => 'application/json'],
    json_encode($data_array)
);

I think that Symphony's request() method is being called: http://symfony.com/doc/current/book/testing.html

like image 65
eoinoc Avatar answered Nov 02 '22 23:11

eoinoc


This is how I go about doing this in Laravel4

// Now Up-vote something with id 53
$this->client->request('POST', '/api/1.0/something/53/rating', array('rating' => 1) );

// I hope we always get a 200 OK
$this->assertTrue($this->client->getResponse()->isOk());

// Get the response and decode it
$jsonResponse = $this->client->getResponse()->getContent();
$responseData = json_decode($jsonResponse);

$responseData will be a PHP object equal to the json response and will allow you to then test the response :)

like image 23
carbontwelve Avatar answered Nov 02 '22 23:11

carbontwelve


Here's what worked for me.

$postData = array('foo' => 'bar');
$postRequest = $this->action('POST', 'MyController@myaction', array(), array(), array(), array(), json_encode($postData));
$this->assertTrue($this->client->getResponse()->isOk());

That seventh argument to $this->action is content. See docs at http://laravel.com/api/source-class-Illuminate.Foundation.Testing.TestCase.html#_action

like image 5
Aaron Pollock Avatar answered Nov 02 '22 21:11

Aaron Pollock