Costruire un frontend prima che l'API sia pronta: Senza Brittle Fixtures (Italiano (Italian))

Costruire un frontend prima che l'API sia pronta: Senza Brittle Fixtures

Saturday, 13 December 2025

//

16 minute read

Introduzione

Quante volte sei stato bloccato aspettando che le API del backend fossero pronte? O hai passato ore a mantenere i dati sfrenati che diventano stantii i cambiamenti dei requisiti del momento?

Entra mostlylucid.mockllmapi - una piattaforma di derisione ASP.NET Core pronta alla produzione che utilizza modelli di lingua larga per generare risposte API realistiche e contestuali al volo. Invece di mantenere i dispositivi JSON, si ottengono derisioni intelligenti che si adattano alle vostre richieste e ricordare lo stato attraverso le chiamate.

Cosa sostiene: Ogni protocollo di cui hai bisogno - REST, GraphQL, gRPC, SignalR, Server-Sent Events e OpenAPI. A differenza dei dispositivi statici, le risposte vengono generate dinamicamente in base al contesto richiesto, rendendo banali flussi di lavoro multi-step e scenari di test complessi.

Collegamenti di progetto

NuGetCity name (optional, probably does not need a translation) NuGetCity name (optional, probably does not need a translation) Rilascio di GitHub Licenza: Unlicense

Tre modi per usarlo

È possibile utilizzare principalmentelucid.mockllmapi in tre modi, a seconda di quanto isolato si desidera che il vostro ambiente dev essere:

  1. Pacchetto ASP.NET Core NuGet - Aggiungi ai tuoi progetti esistenti
  2. Strumento CLI standalone - Eseguibile multipiattaforma (scarica da rilasci)
  3. Contenitore per cani - Zero installazione richiesta

La funzione Killer: Context Memory

Guida completa: Documentazione sui contesti delle API

Le API tradizionali hanno un difetto fatale: ogni richiesta è indipendente. Ottieni un utente con ID 42, quindi prendi i loro ordini, e riceverai ordini per ID utente 99. Nessuna consistenza.

Contesto delle API risolvere questo problema con la memoria condivisa attraverso le relative richieste:

// Request 1: Get a user
// Note: 'context' is a simple query parameter - no cookies or sessions needed
fetch('/api/users/123?context=checkout-session')
// Response: { id: 42, name: "Alice Smith", email: "[email protected]" }

// Request 2: Get orders (same context parameter)
fetch('/api/orders?userId=42&context=checkout-session')
// Response: { userId: 42, customerName: "Alice Smith", items: [...] }
// Perfect! Same user, consistent data

La LLM vede richieste precedenti nello stesso contesto e genera dati coerenti. Questo è il cambio di gioco per i flussi di lavoro multi-step.

Caratteristiche:

Ciclo di vita:

  • Scadenza automatica dopo 15 minuti di inattività (configurabile)
  • Ogni richiesta aggiorna il timer

Comportamento:

  • Estrazione intelligente di TUTTI i campi dalle risposte

Sicurezza:

  • Zero perdite di memoria - contesti puliscono se stessi

Casi di utilizzo:

  • Perfetto per CI/CD - nessun stato tra le corse

Avvio rapido

Opzione 1: Pacchetto NuGet

dotnet add package mostlylucid.mockllmapi
// Program.cs
builder.Services.AddLLMockApi(builder.Configuration);
app.MapLLMockApi("/api/mock");

Opzione 2: Strumento CLI

# Download from https://github.com/scottgal/LLMApi/releases
llmock serve --port 5000

Opzione 3: Docker

Guida completa: Guida alla distribuzione dei docker

git clone https://github.com/scottgal/LLMApi.git
cd LLMApi
docker compose up -d

Prerequisiti: Backend LLM

Hai bisogno di uno di: Ollama, OpenAI, o LM Studio:

# Recommended: Ollama with ministral-3:3b (ultra-fast, accurate JSON generation)
ollama pull ministral-3:3b

Vedi Guida ai modelli di Ollama per tutti i modelli di raccomandazioni e confronti.

Provalo immediatamente.

Una volta eseguito, effettuare la prima richiesta:

curl http://localhost:5000/api/mock/users
# Response: [{"id": 1, "name": "Alice Johnson", "email": "[email protected]"}, ...]

Ecco! Ora hai una finta API funzionante che genera dati realistici su richiesta.

Esempio reale: Cerca da perlopiùlucid.net

Ecco il codice di ricerca reale da questo blog - Questo è codice di frontend di produzione inalterato, nessun adattamento necessario per la simulazione:

// typeahead.js from mostlylucid.net
export function typeahead() {
    return {
        query: '',
        results: [],
        search() {
            fetch(`/api/search/${encodeURIComponent(this.query)}`)
                .then(response => response.json())
                .then(data => { this.results = data; });
        }
    }
}

Muoviti!

# Using CLI
llmock serve --port 5000

# Query returns contextual results
curl http://localhost:5000/api/search/markdown
# LLM generates blog posts about Markdown

curl http://localhost:5000/api/search/docker
# LLM generates blog posts about Docker

Ogni risposta è unica e realistica, adattandosi alla query.

Controllo forma: Definisci il tuo schema

Oltre a generare dati casuali, è spesso necessario un controllo preciso sulla struttura JSON. Il controllo della forma consente di dire all'LLM esattamente quale struttura generare - la caratteristica più potente per lo sviluppo del frontend.

Forma di base

# Without shape - random structure
curl http://localhost:5000/api/mock/users
# Response: { "userId": 1, "fullName": "Alice" }

# With shape - you control it
curl "http://localhost:5000/api/mock/users" \
  -H 'X-Response-Shape: {"id":0,"name":"string","email":"string"}'
# Response: { "id": 1, "name": "Alice", "email": "[email protected]" }

Tre modi per specificare la forma:

  1. Parametro dell' interrogazione - ?shape={...}
  2. Intestazione HTTP - X-Response-Shape: {...} (raccomandato)
  3. Organo richiedente - {"shape": {...}}

Forma nidificata

const shape = {
  company: {
    id: 0,
    name: "string",
    employees: [{
      id: 0,
      firstName: "string",
      department: { id: 0, name: "string" },
      projects: [{ id: 0, title: "string" }]
    }]
  }
};

fetch('/api/mock/company', {
  headers: { 'X-Response-Shape': JSON.stringify(shape) }
});

Allineamento TypeScript

interface User {
  id: number;
  name: string;
  email: string;
}

const USER_SHAPE: Partial<User> = { id: 0, name: "", email: "" };

// Shape becomes your type definition AND mock schema!

Flussi di lavoro multi-step con contesto

Ora combiniamo il controllo della forma con i contesti API per gestire i flussi di lavoro complessi e multi-step. Ricordate la funzione di memoria contestuale di prima? Ecco come brilla nelle operazioni asincrone del mondo reale.

Questo esempio dal servizio di traduzione per lo piùlucid.net mostra come l'LLM mantiene lo stato attraverso un flusso di lavoro completo asincrono:

# Step 1: Start translation
curl -X POST http://localhost:5000/api/translate/start?context=translate-session \
  -d '{"language": "es", "markdown": "# Hello World"}'
# Response: { "taskId": "abc-123", "status": "processing" }

# Step 2: Check status (LLM remembers the task)
curl http://localhost:5000/api/translate/status/abc-123?context=translate-session
# Response: { "taskId": "abc-123", "status": "complete" }

# Step 3: Get result (same taskId!)
curl http://localhost:5000/api/translate/result/abc-123?context=translate-session
# Response: { "taskId": "abc-123", "translatedText": "# Hola Mundo" }

Nota come taskId è coerente con tutte le richieste. Il contesto lo rende possibile.

Oltre il REST: tutti i protocolli

Finora ci siamo concentrati su REST, ma le applicazioni moderne hanno bisogno di più. Che tu stia costruendo con GraphQL, implementando funzionalità in tempo reale con SignalR, o lavorando con i servizi gRPC, per lo piùlucid.mockllmapi ti ha coperto.

Protocolli supportati:

  • ✓ REST
  • GraphQL
  • GRPC
  • ✓ SignalR
  • Eventi inviati dal server (SSE)
  • OpenAPI / Swagger

GraficoQL

Guida: Sezione GraficoQL

curl -X POST http://localhost:5000/api/mock/graphql \
  -d '{"query": "{ users { id name email } }"}'

La query è la forma - non è necessario uno schema separato.

gRPC

Guida completa: Supporto gRPC

# Upload .proto file
curl -X POST http://localhost:5116/api/grpc-protos \
  --data-binary "@user_service.proto"

# Call via JSON or binary Protobuf
curl -X POST http://localhost:5116/api/grpc/userservice/UserService/GetUser \
  -d '{"user_id": 123}'

SignalR in tempo reale

Guida: Guida demo SignalR

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/hub/mock")
    .build();

connection.on("DataUpdate", (message) => {
    console.log(message.data); // Live generated data
});

await connection.start();
await connection.invoke("SubscribeToContext", "stock-prices");

Perfetto per la prototipazione del cruscotto.

Eventi inviati dal server (SSE)

Guida: Modalità di streaming SSE

const eventSource = new EventSource('/api/mock/stream/users');
eventSource.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log('Token:', data.chunk); // Progressive generation
};

OpenAPI / Swagger

Guida completa: Funzionalità OpenAPI

# CLI: Load any OpenAPI spec
llmock serve --spec https://petstore3.swagger.io/api/v3/openapi.json

# All endpoints become live mocks automatically
curl http://localhost:5000/petstore/pet/123

Strumenti pluggabili: mix di dati reali e mock

Guida completa: Strumenti e azioni

A volte è necessario un approccio ibrido - i dati reali dalla produzione combinata con i dati mock generati. Il sistema di strumenti pluggable consente di chiamare API reali durante la generazione mock, creando scenari di test incredibilmente realistici.

{
  "Tools": [{
    "Name": "getUserData",
    "Type": "http",
    "HttpConfig": {
      "Endpoint": "https://api.production.com/users/{userId}",
      "Headers": { "Authorization": "Bearer ${PROD_API_KEY}" }
    }
  }]
}
curl "http://localhost:5000/api/mock/orders?useTool=getUserData&userId=123"

Il mock recupera i dati utente REAL, quindi l'LLM genera ordini usandolo. Estremamente utile per test realistici con flussi di lavoro ibridi simulati/reali.

Integrazione del nucleo ASP.NET

Se si sta costruendo con ASP.NET Core, l'integrazione è senza soluzione di continuità. La bellezza di questo approccio è nessuna modifica del codice ai tuoi servizi - puoi semplicemente configurare HttpClient per indicare il mock durante lo sviluppo e la vera API in produzione.

// Real code from mostlylucid.net
builder.Services.AddHttpClient<IMarkdownTranslatorService, MarkdownTranslatorService>(
    client => {
        var baseUrl = builder.Configuration["TranslationService:BaseUrl"]
            ?? "http://localhost:5000";  // Mock during dev
        client.BaseAddress = new Uri(baseUrl);
    }
);

Appettings. Development.json:

{
  "TranslationService": {
    "BaseUrl": "http://localhost:5000"  // Mock
  }
}

appsettings.Production.json:

{
  "TranslationService": {
    "BaseUrl": "https://api.production.com"  // Real
  }
}

Questo modello funziona per qualsiasi HttpClient nella tua applicazione - servizi di traduzione, gateway di pagamento, API esterne, lo nomini.

Quando usare questo

Prima di tuffarci nelle funzionalità avanzate, cerchiamo di essere chiari su quando questo strumento ha senso per il vostro flusso di lavoro.

Perfetto per:

  • Lo sviluppo di Frontend prima dell'esistenza del backend - Smettila di bloccare le squadre di backend
  • Verifica del flusso di lavoro in più fasi - Context memory gestisce scenari complessi
  • Prototipazione API - Esperimento con forme di risposta prima di commettere
  • Sviluppo offline - Lavorare senza dipendenze di rete
  • Prova dello scenario di errore - Simulare guasti senza interrompere la produzione
  • Gasdotti CI/CD - Nessuna dipendenza esterna significa build più veloci, più affidabili

Non ideale per:

  • Ambienti produttivi - Questo è uno strumento di sviluppo e di prova
  • Dati relativi ai test deterministici - Utilizzare apparecchi quando è necessario l'esatta riproducibilità
  • Prove contrattuali - Convalida sempre contro le API reali per i contratti di produzione

Ora che sai dove si trova, esploriamo le capacità avanzate.

Funzionalità avanzate

Queste caratteristiche sono opzionali - si può ottenere un enorme valore dalle basi da soli. Ma quando avete bisogno di realismo di produzione a scala, questi strumenti sono qui.

Backend LLM multipli

Guida: Backend LLM multipli

# Fast for dev
curl http://localhost:5000/api/mock/users

# High quality for demos
curl "http://localhost:5000/api/mock/users?backend=quality"

# Cloud AI for production-like
curl "http://localhost:5000/api/mock/users?backend=openai"

Simulazione limitazione velocità

Guida: Limitazioni delle tariffe e lottizzazione

Verifica come la tua app gestisce i limiti di velocità:

{
  "EnableRateLimiting": true,
  "RateLimitDelayRange": "500-2000"
}

Simulazione errore

# Test 429 rate limiting
curl "http://localhost:5000/api/mock/users?error=429&errorMessage=Rate%20limit%20exceeded"

# Test 503 unavailable
curl "http://localhost:5000/api/mock/users?error=503"

Supporta tutti i codici 4xx e 5xx.

Caching di risposta

# Generate and cache 10 variants
curl "http://localhost:5000/api/mock/users?shape={\"$cache\":10,\"id\":0,\"name\":\"string\"}"

Le richieste successive ottengono risposte cache istantanee.

Utilità di prova: per lo piùlucid.mockllmapi.Test

Pacchetto di galattosio: per lo piùlucid.mockllmapi.Test

Tutte le caratteristiche di cui sopra sono grandi per lo sviluppo, ma che dire di test automatizzati? Il pacchetto test compagno fornisce una fluente API che rende l'integrazione test una brezza - configurare il comportamento finto dichiarativo e lasciare HttpClient Fai il resto.

Installazione

dotnet add package mostlylucid.mockllmapi.Testing

Uso di base

using mostlylucid.mockllmapi.Testing;

// Create a client with a single endpoint configuration
var client = HttpClientExtensions.CreateMockLlmClient(
    baseAddress: "http://localhost:5116",
    pathPattern: "/users",
    configure: endpoint => endpoint
        .WithShape(new { id = 0, name = "", email = "" })
        .WithCache(5)
);

// Make requests - configuration is automatically applied
var response = await client.GetAsync("/users");
var users = await response.Content.ReadFromJsonAsync<User[]>();

Endpoint multipli

var client = HttpClientExtensions.CreateMockLlmClient(
    "http://localhost:5116",
    configure: handler => handler
        .ForEndpoint("/users", config => config
            .WithShape(new { id = 0, name = "", email = "" })
            .WithCache(10))
        .ForEndpoint("/posts", config => config
            .WithShape(new { id = 0, title = "", content = "", authorId = 0 })
            .WithCache(20))
        .ForEndpoint("/error", config => config
            .WithError(404, "Resource not found"))
);

// Each endpoint automatically uses its configuration
var usersResponse = await client.GetAsync("/users");
var postsResponse = await client.GetAsync("/posts");
var errorResponse = await client.GetAsync("/error"); // Returns 404

Opzioni di configurazione

Configurazione forma:

// Using anonymous objects
.WithShape(new { id = 0, name = "", active = true })

// Using JSON strings
.WithShape("{ \"id\": 0, \"name\": \"\", \"tags\": [] }")

// Complex nested structures
.WithShape(new
{
    user = new { id = 0, name = "" },
    posts = new[] { new { id = 0, title = "" } }
})

Simulazione errori:

// Simple error
.WithError(404)

// With custom message
.WithError(404, "User not found")

// With details
.WithError(422, "Validation failed", "Email address is invalid")

Streaming:

// Enable streaming with token-by-token output
.WithStreaming()
.WithSseMode("LlmTokens")

// Stream complete objects
.WithStreaming()
.WithSseMode("CompleteObjects")

// Stream array items individually
.WithStreaming()
.WithSseMode("ArrayItems")

Iniezione di dipendenza

Client digitato:

services.AddMockLlmHttpClient<IUserApiClient>(
    baseApiPath: "/api/mock",
    configure: handler => handler
        .ForEndpoint("/users", config => config
            .WithShape(new { id = 0, name = "", email = "" }))
);

Client con nome:

services.AddMockLlmHttpClient(
    name: "MockApi",
    baseApiPath: "/api/mock",
    configure: handler => handler
        .ForEndpoint("/data", config => config
            .WithShape(new { value = 0 }))
);

// Usage
var client = httpClientFactory.CreateClient("MockApi");

Esempio di test di integrazione

[Fact]
public async Task Should_Handle_User_Creation()
{
    // Arrange
    var client = HttpClientExtensions.CreateMockLlmClient(
        "http://localhost:5116",
        "/users",
        config => config
            .WithMethod("POST")
            .WithShape(new { id = 0, name = "", email = "", createdAt = "" })
    );

    // Act
    var newUser = new { name = "John Doe", email = "[email protected]" };
    var response = await client.PostAsJsonAsync("/users", newUser);

    // Assert
    response.EnsureSuccessStatusCode();
    var created = await response.Content.ReadFromJsonAsync<User>();
    Assert.NotNull(created);
    Assert.NotEqual(0, created.Id);
}

[Fact]
public async Task Should_Handle_Not_Found_Error()
{
    // Arrange
    var client = HttpClientExtensions.CreateMockLlmClient(
        "http://localhost:5116",
        "/users/999",
        config => config.WithError(404, "User not found")
    );

    // Act
    var response = await client.GetAsync("/users/999");

    // Assert
    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

Come funziona

La MockLlmHttpHandler è un DelegatingHandler che:

  1. Intercetta le richieste HTTP in uscita
  2. Corrisponde alle richieste contro i modelli di endpoint configurati
  3. Inietta la configurazione mock tramite parametri di query e header HTTP
  4. Inoltra la richiesta modificata all'API LLM simulata

Questo consente di utilizzare un reale HttpClient nei tuoi test controllando facilmente il comportamento delle API simulate senza modificare il codice dell'applicazione.

Migliori Pratiche e Suggerimenti

Dopo aver lavorato con questo strumento su più progetti, ecco i modelli che funzionano meglio:

  1. Usare sempre i contesti per i flussi di lavoro - Garantisce ID e dati coerenti attraverso operazioni multi-step
  2. Usare la forma per la sicurezza del tipo - Fallo corrispondere alle tue interfacce TypeScript
  3. Mescolare i dati reali e simulati con gli strumenti - Il meglio di entrambi i mondi.
  4. Scegli il modello giusto (vedere Guida ai modelli di Ollama per dettagli completi):
    • CONSIGLIATO PER DEV: ministral-3:3b (3B params, 32K context) - Killer per Json! RAM ultra-veloce, altamente accurata, minimale
    • Simile alla produzione: llama3 (8B params, contesto 8K) - Miglior equilibrio di qualità e prestazioni
    • Alta qualità: mistral-nemo (12B params, 128K context) - Schemi complessi e set di dati di massa
    • Resource-construed: gemma3:4b oppure phi3 - Alternative più leggere

Documentazione completa

Conclusione

Lo sviluppo di Frontend non deve aspettare le API di backend. mostlylucid.mockllmapi ti dà:

  • Memoria contestuale - Dati coerenti e profumati attraverso flussi di lavoro multi-step
  • Controllo forma - Definizioni precise dello schema che corrispondono ai tuoi tipi
  • Supporto protocollo universale - REST, GraphQL, GRPC, SignalR, SSE, OpenAPI
  • Prove ibride - Mescolare i dati reali di produzione con i morsi generati
  • Zero manutenzione - Nessun dispositivo JSON da aggiornare quando le esigenze cambiano
  • Prove di utilità - API fluente per test di integrazione

La differenza tra questo e il scherno tradizionale? Il tuo frontend funziona contro i dati realistici e contestualmente consapevoli fin dal primo giorno. Niente più "ha funzionato con i dati finti ma non è riuscito con i dati reali" sorprese.

Che tu stia costruendo un blog semplice o un'applicazione enterprise complessa, itererai più velocemente, testerai più accuratamente e spedirai con fiducia.

Pronto per iniziare?

docker compose up -d

Niente backend richiesto.

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.