Saltar al contenido principal
Cuando un paquete necesita consumir una API externa, hay que conseguir dos cosas a la vez: heredar la configuración del cliente HTTP que gestiona Laravel y no arrastrar la configuración de una llamada a la siguiente. Si creas tu propia Factory o conservas durante mucho tiempo una solicitud antes de enviarla, los fakes de la aplicación que usa el paquete pueden dejar de aplicarse. Esta página se basa en la revisión de la implementación de Laravel Framework v13.39.0. Para el uso básico, consulta el cliente HTTP, y para preparar el entorno de pruebas, Pruebas de paquetes.

Comparte la Factory y crea un PendingRequest en cada llamada

El cliente HTTP de Laravel incluye objetos con responsabilidades distintas. FoundationServiceProvider registra la Factory como singleton, y la fachada Http también la resuelve desde el contenedor con el mismo nombre de clase. Por eso, en una aplicación Laravel normal, las solicitudes realizadas con la Factory recibida del contenedor también pueden verificarse con Http::fake(). Es posible diseñar el código usando directamente la fachada, pero en esta página se inyecta la Factory para que las dependencias queden explícitas. Los métodos habituales de configuración de solicitudes, como baseUrl(), que se llaman sobre la Factory se reenvían desde __call() a un nuevo PendingRequest. createPendingRequest() le pasa los callbacks de fake y la restricción de stray requests vigentes en el momento de crearlo, y newPendingRequest() aplica los middleware y las opciones comunes.
Si dentro del paquete creas new Factory() o un cliente de otra biblioteca HTTP, no se heredarán los fakes de la Factory compartida ni Http::preventStrayRequests(). Estas funciones no bloquean las comunicaciones de todo el proceso. En los clientes pensados para Laravel, usa la Factory compartida, y si ofreces un cliente independiente, proporciona un método de prueba específico para ese cliente.

Agrupa las operaciones de la API en un cliente pequeño

Como ejemplo, usaremos el paquete Acme\Catalog, que obtiene productos de una API de catálogo ficticia. src/CatalogClient.php solo guarda la Factory y la URL base, y la solicitud se crea durante la ejecución de product().
Con este diseño, aunque llames a product(42, 'ja') y después a product(42) con el mismo cliente, la cabecera Accept-Language añadida en la llamada anterior no se conserva. La configuración común que la aplicación haya definido en la Factory se sigue aplicando a cada solicitud.
  • La configuración propia del paquete se aplica al PendingRequest recién creado. Evita configurar Http::globalOptions() durante la inicialización del paquete, porque afectaría también a comunicaciones que no tienen relación con él.
  • No envíes nada en el constructor. Diseña el paquete para que resolver el servicio, iniciar Artisan o publicar el archivo de configuración no provoque conexiones a la API externa.
  • throw() convierte las respuestas 4xx y 5xx en RequestException. Distínguelas de ConnectionException, que se produce por fallos de conexión o tiempos de espera agotados, y no sustituyas los fallos por valores de éxito como un array vacío.
  • json(flags: JSON_THROW_ON_ERROR) convierte el JSON no válido en JsonException. El ejemplo solo comprueba si el resultado es un array, así que con una API real valida también los campos obligatorios y los tipos de datos.
Si solo necesitas compartir la URL base o las cabeceras, las macros HTTP de la documentación oficial también son una opción. Si el paquete ofrece operaciones de API, la validación de los valores de retorno y un contrato de excepciones, separarlo en una clase dedicada como esta facilita el mantenimiento. Para el funcionamiento de las macros, consulta el trait Macroable.

Registrar el cliente en el service provider

Prepara la configuración inicial en config/catalog.php del paquete. No guardes aquí clientes HTTP ni closures; incluye solo valores que puedan almacenarse en la caché de configuración.
src/CatalogServiceProvider.php fusiona la configuración y pasa la Factory compartida al resolver el cliente. No sobrescribe el binding de la propia Factory.
El provider se carga, por ejemplo, mediante el descubrimiento automático de paquetes. Quien use el paquete publica la configuración y cambia la URL base en config/acme-catalog.php por la de la API real. El catalog.example.test del ejemplo es un host ficticio para la explicación y los fakes.
En la aplicación, el cliente se resuelve mediante inyección en el constructor o desde el contenedor. La solicitud para obtener el producto se envía por primera vez en esta llamada.
El registro usa bind(), pero si el objeto que guarda el cliente es un singleton, esa referencia no se vuelve a crear cada vez. Lo importante es no guardar en propiedades el idioma, las credenciales ni los objetos de solicitud propios de cada llamada. Para más detalles, consulta Diseño del ciclo de vida de los servicios de paquetes. La sobrescritura de la configuración y la actualización de la caché durante el despliegue se tratan en Fusión y caché de la configuración de paquetes. Gestiona la URL base como configuración de confianza de la aplicación y no permitas que la entrada de una solicitud determine libremente el destino de la conexión.

Verificar el cliente real con fakes

Si haces un mock del propio cliente, no podrás comprobar si usa la Factory compartida ni si construye correctamente la URL y las cabeceras. En las pruebas del paquete, resuelve el CatalogClient real desde el contenedor y simula solo las respuestas HTTP. El siguiente ejemplo se ejecuta en el entorno de pruebas de Orchestra Testbench. En el setUp() de cada prueba se activa preventStrayRequests(). En las pruebas que realizan comunicaciones, configura respuestas solo para las URL esperadas y no añadas un comodín '*'; así también detectarás errores en la URL.
En la segunda prueba, el fake se configura después de resolver el cliente. Como el cliente guarda la Factory y crea el PendingRequest en el momento de la llamada real, el fake se aplica incluso en este orden. Si cambias el diseño para crear y guardar el PendingRequest en el constructor, la prueba detectará que los fakes añadidos después de crearlo no se aplican. assertSent() verifica que exista al menos una solicitud coincidente. Para no pasar por alto envíos adicionales no previstos, combínalo con assertSentCount(). assertSentInOrder() verifica el número y el orden de las solicitudes, por lo que también sirve para comprobar el aislamiento del estado al usar el mismo cliente varias veces seguidas. La protección se configura después de parent::setUp(). Esta prueba por sí sola no permite verificar las comunicaciones realizadas mientras arranca el provider, así que mantén un diseño en el que el registro y el arranque no realicen comunicaciones.
Lo que se puede comprobar con fakes es la solicitud que construye el cliente y el procesamiento de las respuestas preparadas. No garantiza la autenticación del servicio real, la conexión TLS, la duración real de los tiempos de espera ni los cambios en la especificación de la API externa. Las verificaciones que implican conexiones externas se realizan por separado en un entorno de verificación preparado de forma explícita.

Verificaciones adicionales para el mantenimiento a largo plazo

Si separas las responsabilidades de la Factory compartida y de cada PendingRequest, la aplicación puede usar directamente los métodos de prueba habituales de Laravel. En lugar de crear primero un mecanismo de fakes propio, prepara una implementación que pase por la Factory compartida y pruebas que lo comprueben.

Fuentes primarias consultadas

Última modificación el 27 de octubre de 2026