Can I use the Laravel `call` method to send raw JSON data to the unit test?

I am trying to execute a unit test my implementation of the webhook Stripe handler. The banded webhook data falls onto the wire as raw JSON in the body of the POST request, so I capture and decode the data as such:

public function store() { $input = @file_get_contents("php://input"); $request = json_decode($input); return Json::encode($request); } 

I am trying to execute unit test this code, but I can’t figure out how to send raw JSON data to unit test so that I can get it with the file_get_contents("php:input//") function. This is what I tried (using PHPUnit ):

 protected $testRoute = 'api/stripe/webhook'; protected $validWebhookJson = <<<EOT { "id": "ch_14qE2r49NugaZ1RWEgerzmUI", "object": "charge", // and a bunch of other fields too } EOT; public function testWebhookDecdoesJsonIntoObject() { $response = $this->call('POST', $this->testRoute, $this->validWebhookJson); // fails because `$parameters` must be an array $response = $this->call('POST', $this->testRoute, [], [], ['CONTENT_TYPE' => 'application/json'], $this->validWebhookJson); dd($response->getData(true)); // array(0) {} BOOOO!!! Where for to my data go? } 

I also tried curl , but that would make an external request, which makes no sense to me in terms of unit testing. How can I simulate a POST request with raw JSON data in the body that will be picked up by my store method?

+6
source share
6 answers

You can. But you need to send encoded JSON as content (aka request body), not a parameter.

 $this->call( 'POST', '/articles', [], [], [], $headers = [ 'HTTP_CONTENT_LENGTH' => mb_strlen($payload, '8bit'), 'CONTENT_TYPE' => 'application/json', 'HTTP_ACCEPT' => 'application/json' ], $json = json_encode(['foo' => 'bar']) ); 

This is the 7th parameter.

If you look at the definition of a method (in the Laravel core), you can see what it expects.

 public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null) 

Currently, it is not yet supported by Laravel 5.1 tools, fixes, placement, removal of convenience methods.

This supplement is currently being discussed here and here .

EDIT: I have to say that this answer is based on installing Laravel 5.1, so it may not be 100% applicable to you if you are using an older version.

+4
source

You can use the json method described here:

https://laravel.com/api/5.1/Illuminate/Foundation/Testing/TestCase.html#method_json

AS you can see the third parameter - the data array, which in this case will be passed to the request body as json, and if you need to pass additional headers, you can pass them as an array in the fourth parameter.

Example: (Inside your test class)

 public function testRequestWithJSONBody() { $this->json( 'POST', //Method '/', //Route ['key1' => 'value1', 'key2' => 'value2'], //JSON Body request ['headerKey1' => 'headerValue1','headerKey2' => 'headerValue2'] // Extra headers (optional) )->seeStatusCode(200); } 

Hope this helps others.

+3
source

With Laravel 5.1, it's easy to send JSON, just pass in a regular PHP array, and it will be encoded automatically. Example from the docs:

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

From the docs: http://laravel.com/docs/5.1/testing#testing-json-apis

0
source

You can override the post method in CrawlerTrait: https://laravel.com/api/5.1/Illuminate/Foundation/Testing/CrawlerTrait.html

Or create a new helper method, such as the following, that takes one additional optional argument: rawContent

 public function postRawContent($uri, array $data = [], array $headers = [], $rawContent = null) { $server = $this->transformHeadersToServerVars($headers); $this->call('POST', $uri, $data, [], [], $server, $rawContent); return $this; } 
0
source

I wanted to test the JSON sent from the browser to the end. I wanted to put the original json in phpunit, so I did not have to transcode the array that introduced the errors.

To do this, I first converted the json object to a string in javascript (browser or client) and dumped it into the log:

 console.log(JSON.stringify(post_data)) 

Then I copied and put this into the phpunit test, and then decrypted it to an array. Then I just sent this array to json:

 $rawContent = '{"search_fields":{"vendor_table_id":"123","vendor_table_name":"","vendor_table_account_number":"","vendor_table_active":"null"},"table_name":"vendor_table"}'; $this->json('POST', '/vendors', json_decode($rawContent, true)) ->seeJson([ 'id' => 123, ]); 

This was the only way this worked for me after implementing other answers to this post, so I thought I would share it. I am using laravel 5.

0
source

after some work that I fixed, and I did it.

 $response = $this->call( 'POST', "{$this->baseUrl}/{$this->version}/companies/{$company->id}", [ 'name' => 'XPTO NAME', 'email' => ' xpto@example.org ' ], [], [ 'logo_image' => UploadedFile::fake()->image('teste.jpg', 200, 200), 'cover' => UploadedFile::fake()->image('teste.jpg', 1600, 570) ], [ 'CONTENT_TYPE' => HttpContentType::MULTIPART_FORM_DATA, 'HTTP_ACCEPT' => HttpContentType::MULTIPART_FORM_DATA, 'HTTP_X_YOUR_TOKEN' => $authToken->token ] ); $response->assertStatus(HttpStatusCodes::OK);
$response = $this->call( 'POST', "{$this->baseUrl}/{$this->version}/companies/{$company->id}", [ 'name' => 'XPTO NAME', 'email' => ' xpto@example.org ' ], [], [ 'logo_image' => UploadedFile::fake()->image('teste.jpg', 200, 200), 'cover' => UploadedFile::fake()->image('teste.jpg', 1600, 570) ], [ 'CONTENT_TYPE' => HttpContentType::MULTIPART_FORM_DATA, 'HTTP_ACCEPT' => HttpContentType::MULTIPART_FORM_DATA, 'HTTP_X_YOUR_TOKEN' => $authToken->token ] ); $response->assertStatus(HttpStatusCodes::OK); 
0
source

Source: https://habr.com/ru/post/977206/


All Articles