Тестирование контроллеров laravel с телом запроса JSON


Я пытаюсь написать тест phpunit для контроллера Laravel, который ожидает запросы post с телом в формате JSON.

Упрощенная версия контроллера:

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'
        ));
    }
}

В настоящее время у меня есть метод тестирования, который правильно отправляет данные в виде данных формы, закодированных по URL, но я не могу понять, как отправлять данные в формате JSON.

Мой метод тестирования (я использовал github gist здесь при написании теста)

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
    }
}

Я использую angularjs на интерфейсе и по умолчанию запросы, отправляемые на сервер, выполняются в формате JSON. Я бы предпочел не изменять это, чтобы отправлять форму с URL-адресом.

Кто-нибудь знает, как я мог бы написать метод тестирования, который предоставляет контроллеру тело в кодировке JSON?

Author: Reidsy, 2013-01-05

6 answers

Есть намного более простой способ сделать это. Вы можете просто установить свойство Input::$json для объекта, который вы хотите отправить в качестве параметра post. Смотрите Пример кода ниже

 $data = array(
        'name' => 'sample name',
        'email' => '[email protected]',
 );

 Input::$json = (object)$data;

 Request::setMethod('POST');
 $response = Controller::call('client@create');
 $this->assertNotNull($response);
 $this->assertEquals(200, $response->status());

Я надеюсь, что это поможет вам с вашими тестовыми случаями

Обновление: Оригинальная статья доступна здесь http://forums.laravel.io/viewtopic.php?id=2521

 2
Author: Naveen, 2013-02-23 03:28:50

Вот как я собираюсь сделать это в 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 будет объектом PHP, равным ответу json, и позволит вам затем протестировать ответ:)

 7
Author: carbontwelve, 2013-07-10 11:13:07

В Laravel 5 метод call() изменился:

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

Я думаю, что метод Symphony request() вызывается: http://symfony.com/doc/current/book/testing.html

 6
Author: eoinoc, 2015-03-19 12:12:54

Вот что сработало для меня.

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

Этот седьмой аргумент к $this->action равен content. Смотрите документы по адресу http://laravel.com/api/source-class-Illuminate .Основа.Тестирование.Тестовый случай.html#_ действие

 5
Author: Aaron Pollock, 2014-03-12 16:10:47

Простым решением было бы использовать CURL, который затем также позволит вам получить "ответ" с сервера.

class AccountControllerTest extends PHPUnit_Framework_TestCase
{

 public function testLogin()
 {
    $url = "account/login";

    $post_data = array(
        'email' => '[email protected]',
        'password' => 'example_password'
    );
    $content = json_encode($post_data);

    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json"));
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $content);

    $json_response = curl_exec($curl);

    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

    curl_close($curl);

    $response = json_decode($json_response, true);

    // Do some $this->Assert() stuff here on the $status
  }
}

CURL фактически имитирует необработанный HTTP-пост с помощью JSON - так что вы знаете, что действительно тестируете свою функциональность;

 1
Author: Laurence, 2013-01-05 12:45:44

Начиная с Laravel 5.1, существует гораздо более простой способ тестирования контроллеров JSON с помощью PHPUnit. Просто передайте массив с данными, и он будет автоматически закодирован.

public function testBasicExample()
{
    $this->post('/user', ['name' => 'Sally'])
         ->seeJson([
            'created' => true,
         ]);
}

Из документов: http://laravel.com/docs/5.1/testing#testing-json-apis

 0
Author: jimbo2087, 2015-06-09 17:49:37