我正在尝试为Laravel控制器编写一个phpunit测试,该控制器期望使用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'
));
}
}
目前我有一个测试方法正确地将数据作为urlencoded表单数据发送,但我无法弄清楚如何将数据作为JSON发送。
我的测试方法(我在编写测试时使用了github gist here)
class AccountControllerTest extends PHPUnit_Framework_TestCase {
public function testLogin()
{
$post_data = array(
'email' => 'user@example.com',
'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格式。我宁愿不改变它来发送一个urlencoded格式。
有谁知道如何编写一个为控制器提供JSON编码体的测试方法?
答案 0 :(得分:7)
这就是我在Laravel 4中这样做的方式
// 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
将是一个等于json响应的PHP对象,然后允许您测试响应:)
答案 1 :(得分:6)
在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
答案 2 :(得分:5)
这对我有用。
$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.Foundation.Testing.TestCase.html#_action
答案 3 :(得分:2)
这样做有很多简单的方法。您可以简单地将Input :: $ json属性设置为要作为post参数发送的对象。请参阅下面的示例代码
$data = array(
'name' => 'sample name',
'email' => 'abc@yahoo.com',
);
Input::$json = (object)$data;
Request::setMethod('POST');
$response = Controller::call('client@create');
$this->assertNotNull($response);
$this->assertEquals(200, $response->status());
我希望这可以帮助您完成测试用例
获取答案 4 :(得分:1)
一个简单的解决方案是使用CURL - 这将允许您从服务器捕获'响应'。
class AccountControllerTest extends PHPUnit_Framework_TestCase
{
public function testLogin()
{
$url = "account/login";
$post_data = array(
'email' => 'user@example.com',
'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实际上将使用JSON模拟原始HTTP帖子 - 因此您知道您真正在测试您的功能;
答案 5 :(得分:0)
从Laravel 5.1开始,有一种更简单的方法可以通过PHPunit测试JSON控制器。只需传递一个包含数据的数组,它就会自动编码。
public function testBasicExample()
{
$this->post('/user', ['name' => 'Sally'])
->seeJson([
'created' => true,
]);
}
答案 6 :(得分:0)
至少从 Laravel 5.2 开始,Illuminate\Foundation\Testing\Concerns\MakesHttpRequests
中有一个 json()
方法,因此您可以执行以下操作:
$data = [
"name" => "Foobar"
];
$response = $this->json('POST', '/endpoint', $data);
此外,从 Laravel 5.3 开始,还有一些方便的方法,例如 putJson()
、postJson()
等。因此它甚至可以进一步缩短为:
$data = [
"name" => "Foobar"
];
$response = $this->postJson('/endpooint', $data);
然后你可以像这样$response->assertJson(...)
:
$response->assertJson(fn (AssertableJson $json) => $json->hasAll(['id', 'name']));