Los siete paquetes .NET

Los siete paquetes siguientes están disponibles en NuGet.org en la versión 0.2.10. Mantén sus versiones alineadas dentro de cada aplicación.

Los ejemplos de las bibliotecas usan 0.2.10 en proyectos .NET 10 y también admiten .NET 8 y .NET 9. La herramienta echo-mock requiere .NET 10. Instalar un paquete por sí solo no activa mocks ni valida contratos.

Antes de ejecutar un ejemplo con red, configura GAPFY_ECHO_BASE_ADDRESS con la dirección base de tu API Echo, incluida la barra final, y GAPFY_ECHO_API_KEY mediante el entorno o tu almacén de secretos. Usa la dirección de la API, no la URL pública del mock. Las claves nuevas se emiten en Aplicaciones de Maestro, una función de Echo Pro y Pro AI que requiere Echo/ManageHosting; el administrador de la organización recibe este permiso por defecto con un plan de pago y puede concedérselo a otro rol. El feed de reglas es GET api/echo/mock/rules en la dirección base configurada. Sin una clave, el endpoint devuelve 401. Devuelve 403 si la clave no tiene ServeMocks o si la organización no tiene una suscripción Echo de pago en vigor.

Gapfy.Echo.Contracts

Publica una versión de un contrato que ofrece tu aplicación. Primero crea el contrato y su vínculo Provides en Maestro, emite una clave con PublishOwnedContracts y define GAPFY_ECHO_CONTRACT_ID. Guarda un documento de contrato Echo del editor como orders.echo.json en el directorio de trabajo del proceso. Debe ser el documento Echo, no una respuesta de ejemplo ni un JSON Schema sin convertir.

dotnet new console -n EchoContractsDemo -f net10.0
dotnet add EchoContractsDemo package Gapfy.Echo.Contracts --version 0.2.10
using System.Net.Http.Headers;
using Gapfy.Echo.Contracts;

string Required(string name) =>
    Environment.GetEnvironmentVariable(name)
    ?? throw new InvalidOperationException($"Set {name}.");

using var http = new HttpClient
{
    BaseAddress = new Uri(Required("GAPFY_ECHO_BASE_ADDRESS"))
};
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Required("GAPFY_ECHO_API_KEY"));

var publisher = new EchoContractPublicationClient(http);
var documentJson = await File.ReadAllTextAsync("orders.echo.json");
var publication = await publisher.PublishAsync(
    Guid.Parse(Required("GAPFY_ECHO_CONTRACT_ID")), documentJson);

Console.WriteLine(publication.AssignedVersion.Version);
Console.WriteLine(publication.Created);

El paquete también ofrece el códec, el validador y los motores de inferencia y evaluación de contratos. El resultado de publicación incluye Changes con evaluaciones de consumidor y proveedor. Una evaluación incompatible describe una publicación ya completada; no la deshace. Un contenido idéntico puede devolver Created = false con una versión existente.

Gapfy.Echo.Testing

Comprueba los contratos consumidos por la aplicación con una clave ReadBoundContracts. La llamada lanza una excepción si encuentra un cambio incompatible, por lo que puedes usarla en tu framework de pruebas. Este ejemplo exige que responda el servicio remoto en vez de permitir un resultado positivo sin conexión.

dotnet new console -n EchoTestingDemo -f net10.0
dotnet add EchoTestingDemo package Gapfy.Echo.Testing --version 0.2.10
using Gapfy.Echo.Testing;

var echo = GapfyEchoValidation.Create(new GapfyEchoValidationOptions
{
    RequireRemote = true
});

await echo.Contracts.ValidateAsync();

En la primera ejecución local correcta, el paquete crea instantáneas EchoContracts junto al proyecto. Revísalas e inclúyelas en un commit. El CI se niega a crear instantáneas que falten. Sin RequireRemote = true, un servicio inaccesible puede producir un resultado positivo sin conexión usando las instantáneas del repositorio; el informe explica qué no se comprobó. Esto no verifica el contrato remoto actual ni la API en ejecución. Acepta cambios en las instantáneas de forma deliberada en una estación de trabajo, nunca automáticamente en CI.

Usa CheckAsync() si necesitas el informe sin una excepción, u Only("partner-orders") para comprobar vínculos seleccionados. Una selección desconocida falla en vez de no comprobar nada. Tras revisar en una estación de trabajo, AcceptAsync("partner-orders") actualiza una referencia y AcceptAllAsync() las actualiza todas; el CI rechaza esa aceptación. Activa TreatWarningsAsErrors para tratar avisos como fallos e indica UnmappedMemberHandlingDisallow o ExhaustiveStatusHandling cuando esas condiciones se apliquen al consumidor.

Gapfy.Echo.Mock.Client

Intercepta llamadas salientes solo en los HttpClient creados por la factoría que actives. Este ejemplo expone /probe y llama a la URL real de PARTNER_API_URL mediante el cliente activado. Define DOTNET_ENVIRONMENT=Development para uso local y proporciona una clave ServeMocks. Obtener las reglas forma parte de Echo Pro y Pro AI; un mock del escritorio en Free no necesita este paquete.

dotnet new web -n EchoMockClientDemo -f net10.0
dotnet add EchoMockClientDemo package Gapfy.Echo.Mock.Client --version 0.2.10
using Gapfy.Echo.Mock.Client;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEchoMock(x =>
{
    x.ApiKey = builder.Configuration["GAPFY_ECHO_API_KEY"];
    x.RuleServiceUri = new Uri(
        builder.Configuration["GAPFY_ECHO_BASE_ADDRESS"]
        ?? throw new InvalidOperationException("Set GAPFY_ECHO_BASE_ADDRESS."));
});
builder.Services.AddHttpClient("partner").AddEchoMockInterception();

var app = builder.Build();

app.MapGet("/probe", async (IHttpClientFactory factory) =>
{
    var target = app.Configuration["PARTNER_API_URL"]
        ?? throw new InvalidOperationException("Set PARTNER_API_URL.");
    return await factory.CreateClient("partner").GetStringAsync(target);
});

app.Run();

Las reglas estáticas y de contrato pueden responder dentro de tu aplicación. Las respuestas de contrato se generan con Gapfy.Echo.Contracts y admiten X-Echo-Scenario y X-Echo-Seed. Un contrato ausente o inválido, o un fallo de generación, devuelve 502 application/problem+json sin llamar al servicio real. Las llamadas sin coincidencia y las anteriores a la primera carga de reglas siguen hacia el servicio real. Si se pierde el plan de pago, la actualización de reglas devuelve 403 y escribe un aviso, pero la aplicación sigue funcionando. Las reglas ya cargadas, incluso desde una copia local, pueden seguir interceptando; sin reglas, las llamadas pasan al servicio real. No intercepta un HttpClient creado manualmente, un canal gRPC ni un SDK con transporte propio. El paquete no puede activarse en Production ni Prod; otros entornos fuera de Development requieren una aceptación explícita.

Gapfy.Echo.Mock.Server

Añade middleware de mocks a tu API ASP.NET Core con una clave ServeMocks. Obtener las reglas forma parte de Echo Pro y Pro AI. En este ejemplo, /health sigue siendo un endpoint real. Las rutas que la API todavía no implementa pueden responder mediante reglas de Echo. Coloca el middleware después del enrutamiento y antes de ejecutar los endpoints, como en este ejemplo con WebApplication.

dotnet new web -n EchoMockServerDemo -f net10.0
dotnet add EchoMockServerDemo package Gapfy.Echo.Mock.Server --version 0.2.10
using Gapfy.Echo.Mock.Server;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEchoMock(x =>
{
    x.ApiKey = builder.Configuration["GAPFY_ECHO_API_KEY"];
    x.BaseAddress = new Uri(
        builder.Configuration["GAPFY_ECHO_BASE_ADDRESS"]
        ?? throw new InvalidOperationException("Set GAPFY_ECHO_BASE_ADDRESS."));
});

var app = builder.Build();

app.MapEchoMock();
app.MapGet("/health", () => Results.Ok(new { status = "ok" }));

app.Run();

Las rutas implementadas y las peticiones sin coincidencia siguen hacia tu API. Las reglas estáticas devuelven cuerpos guardados; las reglas de contrato generan respuestas a partir del documento. Usa X-Echo-Scenario para elegir un escenario guardado y X-Echo-Seed para repetir los valores generados. Un contrato inválido o un fallo de generación devuelve 502 en vez de llamar al código real. Mock.Server se activa fuera de Production por defecto; Production exige la opción explícita EnableInProduction. Sin reglas cargadas, las peticiones pasan normalmente. Una actualización fallida conserva las últimas reglas en caché.

Si la interceptación deja de funcionar y la configuración parece correcta, comprueba la suscripción Echo de tu organización y el scope ServeMocks antes de buscar un fallo en tu código. Crear y probar mocks en el escritorio y trabajar con contratos en Maestro sigue incluido en Free; publicar en el servicio público y cargar reglas para estos dos paquetes requiere Echo Pro o Pro AI.

Gapfy.Echo.ApiExplorer

Añade Echo API Explorer a tu aplicación ASP.NET Core. Consulta endpoints HTTP y descripciones OpenAPI, prepara una petición y examina la respuesta dentro de la propia aplicación. Puedes elegir respuestas reales o mocks de Echo por controller o endpoint, incluso para operaciones ya implementadas.

dotnet new web -n EchoExplorerDemo -f net10.0
dotnet add EchoExplorerDemo package Gapfy.Echo.ApiExplorer --version 0.2.10
using Gapfy.Echo.ApiExplorer;
using Microsoft.AspNetCore.Authentication.Cookies;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication("Application")
    .AddCookie("Application", x => x.LoginPath = "/account/login");
builder.Services.AddAuthorization(x =>
{
    x.AddPolicy("Echo.View", x => x.RequireAuthenticatedUser()
        .RequireRole("EchoViewer", "EchoDeveloper", "EchoAdministrator"));
    x.AddPolicy("Echo.Execute", x => x.RequireAuthenticatedUser()
        .RequireRole("EchoDeveloper", "EchoAdministrator"));
    x.AddPolicy("Echo.Session", x => x.RequireAuthenticatedUser()
        .RequireRole("EchoDeveloper", "EchoAdministrator"));
    x.AddPolicy("Echo.Instance", x => x.RequireAuthenticatedUser()
        .RequireRole("EchoAdministrator"));
});
builder.Services.AddEchoDeveloperUI(builder.Configuration.GetSection("Echo"), x =>
{
    x.ApplicationName = "Orders.API";
    x.UI.RoutePrefix = "/tools/echo";
    x.UI.ManageSessionPolicy = "Echo.Session";
    x.UI.ManageInstancePolicy = "Echo.Instance";
});

var app = builder.Build();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEchoDeveloperUI();
app.MapEchoDeveloperUI();
app.MapGet("/api/orders", () => Results.Ok(new[] { new { id = 1 } }))
    .RequireAuthorization()
    .WithEchoMocking();
app.Run();

Este ejemplo incluye el registro completo. Espera que la ruta de inicio de sesión de tu aplicación, /account/login, emita la cookie Application con los roles necesarios. Conecta el registro a la autenticación y los permisos existentes; el paquete no crea cuentas ni concede acceso. Configura Echo:ApiBaseAddress y Echo:ApiKey en tu proveedor de configuración protegido con una clave ServeMocks. Tras iniciar sesión, abre /tools/echo en la dirección de la aplicación. El host decide en qué entornos habilita el panel. Mantén la autorización de negocio antes de UseEchoDeveloperUI; los endpoints Minimal API necesitan WithEchoMocking().

Elige el alcance antes de aplicar

  1. Empieza con Mi sesión para probar el cambio mediante tu executor del panel. Los demás clientes siguen usando el perfil de la instancia.
  2. Elige un controller o endpoint, selecciona el servidor mock y la ruta, y elige un escenario si lo hay. La selección del endpoint prevalece sobre la del controller; la herencia usa la selección superior.
  3. Aplica el perfil, envía una petición desde el executor y examina el resultado. Seleccionar un servidor o cambiar de pestaña no aplica el borrador.
  4. Elige Toda la instancia cuando el cambio deba afectar a todos los clientes de esa instancia. Requiere permiso de gestión de instancia y confirmar el perfil pendiente.

Los perfiles personales caducan y dejan de ser válidos si cambia la configuración de referencia de la instancia. Recarga y revisa el nuevo estado cuando se solicite. Si el mock elegido no está disponible, Echo muestra un error sin ejecutar silenciosamente el código real. La autenticación y los filtros anteriores al handler siguen vigentes; el código dentro del handler sustituido no se ejecuta.

El executor acepta parámetros, cabeceras, cuerpos y credenciales. Entrar en el panel y autenticar la petición son acciones separadas. El host puede habilitar inicio de sesión OpenID Connect en el navegador o una sesión Bearer breve con su validación de tokens existente; son alternativas. Los tokens de sesión permanecen en la memoria del servidor, caducan y se pierden al reiniciar. El inicio de sesión en el navegador exige HTTPS. La cookie del panel no autentica las llamadas habituales a la aplicación.

La interfaz ofrece siete idiomas y conserva la elección del navegador. Las descripciones de la API, los nombres de campos JSON y los payloads mantienen el contenido original. El host puede limitar los endpoints visibles y habilitar aislamiento por organización; en ese modo, los cambios de instancia afectan solo a la organización autenticada. El paquete actual admite HTTP y no ofrece API Explorer para gRPC.

Gapfy.Echo.Offline

Guarda una configuración de mocks revisada en un snapshot portátil para ejecutar pruebas sin consultar Echo. El snapshot contiene la revisión del perfil, los endpoints HTTP seleccionados, reglas y contratos completos, escenarios y seed. No contiene la clave de aplicación Echo ni las credenciales del executor.

Exporta el perfil de la instancia desde API Explorer con permiso de gestión de instancia. Después usa echo-mock export, más abajo, para obtener las reglas seleccionadas mientras tienes conexión. La biblioteca lee y valida el archivo resultante:

dotnet new console -n EchoOfflineDemo -f net10.0
dotnet add EchoOfflineDemo package Gapfy.Echo.Offline --version 0.2.10
using Gapfy.Echo.Offline;

var snapshot = await EchoOfflineSnapshotCodec.ReadAsync("echo.snapshot.json");
EchoOfflineSnapshotCodec.Validate(snapshot);
Console.WriteLine(snapshot.ContentHash);

La validación comprueba el hash del contenido, los contratos y la cobertura completa de las rutas antes de ejecutar. SHA-256 detecta cambios en el snapshot; no identifica al autor ni concede acceso. Trata los cuerpos de respuesta del archivo como datos de prueba que pueden necesitar acceso restringido. No se puede ejecutar un snapshot con reglas incompletas o sin ninguna selección de mock.

La aplicación que importa el snapshot mediante API Explorer debe configurar explícitamente el modo offline y coincidir con las identidades de aplicación, workspace, perfil y endpoints. Un snapshot de organización también debe corresponder a esa organización. Los perfiles importados son de solo lectura y no actualizan un catálogo remoto.

Gapfy.Echo.Mock.Runner

Instala el comando echo-mock para ejecutar snapshots HTTP preparados. Es independiente de gapfy-echo, que ejecuta colecciones y cadenas.

dotnet tool install --global Gapfy.Echo.Mock.Runner --version 0.2.10
echo-mock export --profile echo.mock.json --server https://api.example.test/ --key-env ECHO_API_KEY --output echo.snapshot.json --seed 17
echo-mock validate --snapshot echo.snapshot.json --report validation.json
echo-mock run --snapshot echo.snapshot.json --report execution.json --timeout 300 -- dotnet Tests.dll --minimum-expected-tests 1

Sustituye la dirección de ejemplo por la dirección configurada de la API Echo. Define ECHO_API_KEY mediante el entorno o los secretos del CI; el comando de exportación recibe el nombre de la variable, sin pasar el secreto como argumento. La clave necesita ServeMocks y acceso al feed de reglas de pago. Prepara la herramienta, el runtime .NET y las pruebas compiladas antes de la fase offline.

run valida el snapshot, abre un listener privado en loopback e inicia el comando después de --. Usa el comando real de pruebas del proyecto; el ejemplo espera una aplicación de pruebas Microsoft.Testing.Platform ya compilada y exige al menos una prueba. El proceso hijo recibe ECHO_MOCK_BASE_ADDRESS y los ajustes Echo__Offline__*. Los consumidores de API Explorer usan el perfil importado; los consumidores HTTP directos usan /servers/{serverId} seguido de la ruta de la regla.

Una seed fija estabiliza los valores aleatorios. Los generadores que dependen de fechas pueden seguir cambiando con el tiempo; usa fechas constantes cuando necesites repetición exacta. Las rutas desconocidas devuelven 404 en vez de consultar un servicio real. El runner no bloquea el resto del tráfico de red de la aplicación probada.

Usa serve --snapshot echo.snapshot.json --port 0 --ready-file ready.json cuando otro proceso deba controlar la ejecución. El archivo de disponibilidad y /_echo/ready identifican el snapshot validado. Una cancelación o un timeout detiene el listener y el proceso hijo del runner. El informe JSON registra el hash, los recuentos de rutas y el resultado del hijo, sin cuerpos de petición ni credenciales. Los códigos de salida son 0 para éxito, 2 para entrada inválida, 3 para fallo de ejecución o ruta sin coincidencia y 130 para cancelación; un hijo que falla conserva su propio código de salida.

Elige la vía adecuada