Juan Ariel Vasquez Hernandez
Juan Ariel Vasquez Hernandez
Laravel
Comparte:

Test: crear nuestro propio metodo json para agregar los headers

Que tal Jorge mucho gusto,
Tengo una duda, a que se debe que si realizo el return $this->json() entrara en un lup infinito sino que debo hacerlo al padre del json
Gracias de antemano por los detalles

gssa
gssa (986 xp)
Hola Ariel, para que los chicos que estemos en aprendible, podamos apoyarte a solucionar un problema que tengas en tu codigo, es muy importante que nos ayudes a nosotros primero, compartiendonos el codigo de tu funcion y de ser posible el contexto de como,  y que estas intentando hacer, para que, asi se pueda dar una mejor respuesta a tus preguntas, saludos
Jorge García
Jorge García (2780 xp)
Al parecer esta pregunta tiene que ver con el curso Desarrollo de una API con Laravel, voy a tratar de explicarlo por aquí, me comentas si queda claro.

Tenemos el Trait MakesHttpRequests de Laravel 
<?php

namespace Illuminate\\Foundation\\Testing\\Concerns;

trait MakesHttpRequests 
{
    public function json($method, $uri, array $data = [], array $headers = [])
    {
        $files = $this->extractFilesFromDataArray($data);

        $content = json_encode($data);

        $headers = array_merge([
            'CONTENT_LENGTH' => mb_strlen($content, '8bit'),
            'CONTENT_TYPE' => 'application/json',
            'Accept' => 'application/json',
        ], $headers);

        return $this->call(
            $method,
            $uri,
            [],
            $this->prepareCookiesForJsonRequest(),
            $files,
            $this->transformHeadersToServerVars($headers),
            $content
        );
    }
}


Este método es el que se utiliza para hacer peticiones en los TESTS, y este archivo viene con Laravel, así que no lo podemos editar.
 
Por este motivo creamos un nuevo Trait MakesJsonApiRequests
 
<?php

namespace Illuminate\\Foundation\\Testing\\Concerns;

trait MakesJsonApiRequests 
{
		public function json($method, $uri, array $data = [], array $headers = []): TestResponse
    {
        if ($this->addJsonApiHeaders) {
            $headers['accept'] = 'application/vnd.api+json';

            if ($method === 'POST' || $method === 'PATCH') {
                $headers['content-type'] = 'application/vnd.api+json';
            }
        }

        if ($this->formatJsonApiDocument) {
            if (! isset($data['data'])) {
                $formattedData = $this->getFormattedData($uri, $data);
            }
        }

        return parent::json($method, $uri, $formattedData ?? $data, $headers);
    }
}


En la clase abstracta, TestCase estamos utilizando este Trait
 
<?php

namespace Tests;

use Illuminate\\Foundation\\Testing\\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication, MakesJsonApiRequests;
}


Todos los tests de la carpeta Feature, se extienden a esta clase TestCase, por lo que heredan todos lo métodos del trait y de la clase base TestCase.
 
Ahora, vamos a ver un ejemplo de uno de los tests que tenemos:
 
<?php

namespace Tests\\Feature\\Articles;

use Tests\\TestCase;
use App\\Models\\Article;
use Illuminate\\Foundation\\Testing\\RefreshDatabase;

class ListArticlesTest extends TestCase
{
    use RefreshDatabase;

    /** @test */
    public function can_fetch_articles()
    {

        $this->json(route('api.v1.articles.index'));

        ...
    }
}


Debemos entender que la palabra (o keyword) $this hace referencia a la clase ListArticlesTest y al ejecutar $this->json() se va a buscar un método llamado json dentro de la clase ListArticlesTest y como podemos observar, no existe dicho método, sin embargo, al estar extendiendo a la clase TestCase que a su vez utiliza el trait MakesJsonApiRequests que sí contiene la clase json entonces esa es la que se va a ejecutar.
 
Ahora, vamos a concentrarnos en el trait MakesJsonApiRequests
 
<?php

namespace Illuminate\\Foundation\\Testing\\Concerns;

trait MakesJsonApiRequests 
{
		public function json($method, $uri, array $data = [], array $headers = []): TestResponse
    {
        // ...
				
				// La pregunta es por qué llamamos al parent::json en lugar de this->json
        return parent::json($method, $uri, $formattedData ?? $data, $headers);
    }
}


En este contexto, parent hace referencia a la clase abstracta TestCase que contiene otro método json
 
Si hacemos lo siguiente se creará un loop infinito y la aplicación se detendrá:
 
<?php

namespace Illuminate\\Foundation\\Testing\\Concerns;

trait MakesJsonApiRequests 
{
		public function json($method, $uri, array $data = [], array $headers = []): TestResponse
    {
        // ...
				
				// En este caso se va a llamar al mismo método json, una y otra vez...
        return $this->json($method, $uri, $formattedData ?? $data, $headers);
    }
}


En este caso estamos llamando al método json del trait MakesJsonApiRequests y dentro del método, estamos llamando nuevamente a sí mismo, al mismo método json por lo que se genera el bucle infinito.
 
Jorge García
Jorge García (2780 xp)
Muchas gracias por tu respuesta, esta pregunta tiene que ver con el curso Desarrollo de una API con Laravel.