11

我正在尝试为 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)

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 编码主体的测试方法?

4

7 回答 7

9

在 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

于 2015-03-19T12:12:54.057 回答
6

这就是我在 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将是一个等于 json 响应的 PHP 对象,并允许您测试响应:)

于 2013-07-10T11:13:07.610 回答
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->actioncontent请参阅http://laravel.com/api/source-class-Illuminate.Foundation.Testing.TestCase.html#_action上的文档

于 2014-03-12T16:10:47.153 回答
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());

我希望这对您的测试用例有所帮助

更新:原始文章可在此处获得http://forums.laravel.io/viewtopic.php?id=2521

于 2013-01-19T01:47:25.940 回答
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 帖子——因此您知道您正在真正测试您的功能;

于 2013-01-05T12:45:44.330 回答
1

从 Laravel 5.1 开始,有一种更简单的方法可以通过 PHPunit 测试 JSON 控制器。只需传递一个包含数据的数组,它就会自动编码。

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

来自文档: http: //laravel.com/docs/5.1/testing#testing-json-apis

于 2015-06-09T17:49:37.207 回答
0

由于至少 Laravel 5.2 有一个json()方法, Illuminate\Foundation\Testing\Concerns\MakesHttpRequests因此您可以执行以下操作:

$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']));
于 2021-03-22T19:23:11.887 回答