Je crée une API avec Laravel 5
Et je la teste avec PHPUnit
. Je dois tester la compatibilité de la fonctionnalité existante, qui est un POST XML. Pour l'instant, mon premier test ressemble à ceci:
public function testPostMessages()
{
$response = $this->call('POST', 'xml');
$this->assertEquals(200, $response->getStatusCode());
}
Ceci passe très bien. Suivant sur ma liste envoie réellement les données XML avec le POST. Donc pour mon deuxième test, j'ai:
public function testPostMessagesContent()
{
$response = $this->call('POST', 'xml');
$this->assertTrue(is_valid_xml($response->getContent()));
}
Ce test échoue. Cependant, je n'envoie pas mes données XML. Comment puis-je envoyer mon XML?
Après cela, je dois ajouter la fonctionnalité pour obtenir le contenu de la demande. Je sais qu'il y a un objet Request
avec lequel je peux interagir, mais je ne sais pas exactement quelle méthode utiliser. Comment puis-je obtenir mon code XML à partir de mon contrôleur?
J'ai pu obtenir des résultats entre-temps. Mon test actuel ressemble à ceci:
public function testPostMessagesContent()
{
$response = $this->call('POST', 'xml', array('key' => 'value'), array(), array(), array('content' => 'content'));
$this->assertContains('~', $response->getContent());
}
J'ai seulement le tilde ici parce que je sais qu'il ne correspondra pas pour que je puisse voir toute la réponse. Dans XmlController.php
J'ai:
class XmlController extends Controller {
public function index(Request $request)
{
return $request;
}
}
Ma sortie de PHPUnit
est la suivante:
1) XmlTest::testPostMessagesContent
Failed asserting that 'POST xml HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Language: en-us,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Host: localhost
User-Agent: Symfony/2.X
' contains "~".
Où sont mes paramètres et mon contenu? J'ai l'impression de n'utiliser que call()
de manière incorrecte.
J'ai mis à jour mon contrôleur pour qu'il utilise Request:all()
comme suit:
class XmlController extends Controller
{
public function index()
{
$content = Request::all();
return $content;
}
}
Cela a renvoyé ma paire clé-valeur, mais pas le contenu.
1) XmlTest::testPostMessagesContent
Failed asserting that '{"key":"value"}' contains "~".
Les paires clé-valeur sont bonnes; c'est un progrès. Cependant, ce dont j'ai vraiment besoin, c'est du contenu puisque je recevrai ces données dans la partie contenu de la demande. Si j'utilise Request::getContent()
, je récupère une chaîne vide. Voici mon appel dans le test:
$response = $this->call('POST', 'xml', array('key' => 'value'), array(), array(), array('content' => 'content'));
Voici mes résultats de test:
1) XmlTest::testPostMessagesContent
Failed asserting that '' contains "~".
Je ne parviens pas à obtenir le contenu du corps d'une requête HTTP. Comme XML ne fonctionnait pas, j'ai avancé avec la partie REST de mon API, qui utilise JSON. Voici un de mes tests:
public function testPostMessagesContent()
{
$response = $this->call('POST', 'messages', ['content' => 'content']);
$this->assertEquals('saved!', $response->getContent());
}
Ce test est réussi. Si j'utilise curl, je reçois également un appel réussi:
curl -X POST -d "content=my_new_content" "http://localhost:8000/messages"
Cela retourne 'saved!'
C'est génial, mais si j'essaie d'utiliser curl dans un script autonome PHP (pour simuler un client), voici ce qui est retourné:
Array ( [url] => http://localhost:8000/messages [content_type] => text/html; charset=UTF-8 [http_code] => 302 [header_size] => 603 [request_size] => 118 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.063977 [namelookup_time] => 0.000738 [connect_time] => 0.000866 [pretransfer_time] => 0.000943 [size_upload] => 12 [size_download] => 328 [speed_download] => 5126 [speed_upload] => 187 [download_content_length] => -1 [upload_content_length] => 12 [starttransfer_time] => 0.057606 [redirect_time] => 0 [certinfo] => Array ( ) [primary_ip] => ::1 [primary_port] => 8000 [local_ip] => ::1 [local_port] => 63248 [redirect_url] => http://localhost:8000 [request_header] => POST /messages HTTP/1.1 Host: localhost:8000 Accept: */* Content-type: text/xml Content-length: 12 ) Redirecting to http://localhost:8000.
Voici ma commande curl ajoutant les champs POST:
curl_setopt($ch, CURLOPT_POSTFIELDS, 'content=test');
Il me semble que POSTFIELDS est ajouté au corps de la demande. Dans ce cas, j'ai toujours le même problème. Je ne parviens pas à obtenir le contenu du corps de mes en-têtes HTTP. Après avoir commenté ma validation, je reçois:
Array ( [url] => http://localhost:8000/messages [content_type] => text/html; charset=UTF-8 [http_code] => 200 [header_size] => 565 [request_size] => 118 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.070225 [namelookup_time] => 0.000867 [connect_time] => 0.00099 [pretransfer_time] => 0.001141 [size_upload] => 12 [size_download] => 6 [speed_download] => 85 [speed_upload] => 170 [download_content_length] => -1 [upload_content_length] => 12 [starttransfer_time] => 0.065204 [redirect_time] => 0 [certinfo] => Array ( ) [primary_ip] => ::1 [primary_port] => 8000 [local_ip] => ::1 [local_port] => 63257 [redirect_url] => [request_header] => POST /messages HTTP/1.1 Host: localhost:8000 Accept: */* Content-type: text/xml Content-length: 12 ) saved!
J'ai donc mon message 'saved!'
. Génial! Mais, dans ma base de données, j'ai maintenant une ligne vide. Pas génial. Il ne voit toujours pas le contenu du corps, juste les en-têtes.
Je cherche les réponses à ces questions:
Le contrôleur interne injecte un objet Request. Par conséquent, si vous souhaitez accéder au corps de la demande dans la méthode du contrôleur 'foo', procédez comme suit:
public function foo(Request $request){
$bodyContent = $request->getContent();
}
Vous pouvez passer data comme troisième argument de call()
. Ou, en fonction de votre API, il est possible que vous souhaitiez utiliser le sixième paramètre.
De la docs :
$this->call($method, $uri, $parameters, $files, $server, $content);
Je ne pense pas que vous souhaitiez obtenir les données de votre demande , je pense que vous souhaitez obtenir les données de votre réponse . Les deux sont différents. Aussi, vous devriez construire votre réponse correctement dans votre contrôleur.
En regardant la classe dans la deuxième édition, je lui donnerais l'aspect suivant:
class XmlController extends Controller
{
public function index()
{
$content = Request::all();
return Response::json($content);
}
}
Une fois que vous en êtes arrivé là, vous devriez vérifier le contenu de votre réponse dans votre scénario de test (utilisez print_r si nécessaire), vous devriez voir les données à l'intérieur.
Plus d'informations sur les réponses Laravel ici:
Pour ceux qui obtiennent encore une réponse vide avec $request->getContent()
, vous pouvez utiliser:
$request->all()
par exemple:
public function foo(Request $request){
$bodyContent = $request->all();
}