Тестирование контроллеров 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?
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
Вот как я собираюсь сделать это в 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, и позволит вам затем протестировать ответ:)
В 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
Вот что сработало для меня.
$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#_ действие
Простым решением было бы использовать 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 - так что вы знаете, что действительно тестируете свою функциональность;
Начиная с 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