Mocks, stubs, fakes e emuladores: testar chamadas de API com agentes de codificação

Quando o teu código chama uma API, precisas de uma forma de a testar sem esperar que a API real falhe. Tens 5 tipos de substitutos para escolher. As pessoas usam os nomes de forma vaga, por isso aqui está como este artigo os utiliza:

  • Stub: um substituto no processo para o seu cliente HTTP ou chamada SDK que devolve uma resposta pré-definida. É rápido e repetível, e testa a lógica da resposta que escreveste.
  • Mock: um stub que também regista como o teu código o chamou, para que o teste possa verificar as chamadas. Chega até um stub.
  • Servidor falso: um pequeno servidor funcional, muitas vezes em memória, a que a tua aplicação acede via HTTP em vez da API real. Exerce o seu cliente HTTP, mas tem de apontar a aplicação para a URL dela.
  • Emulador: uma versão local de um serviço, normalmente publicada pelo proprietário do serviço, que se comporta como o verdadeiro para as operações que suporta. Verifique quais os limites e falhas que cobre antes de confiar nele para o tratamento de erros.
  • Proxy de interceção: fica na rede entre a sua aplicação e a API. A tua aplicação chama a URL real, e o proxy encaminha os pedidos ou responde a alguns deles com a resposta que defines. A sua aplicação tem de enviar o seu tráfego através do proxy e, para HTTPS, confiar no certificado do proxy.

Como testar código que chama uma API

Approach O que testa Aquilo de que precisa Logo quando
stub ou mock A tua lógica para uma resposta específica O seu framework de teste Testa lógica de negócio, análise sintática e ramos de erro em testes unitários
Servidor falso O seu cliente HTTP e a sua serialização Uma definição base de URL ou um interruptor de configuração na tua aplicação A API ainda não existe, ou então precisas de um backend estável para trabalhar com UI
Emulator Comportamento próximo do serviço real para operações suportadas Um endpoint ou cadeia de ligação diferente O proprietário do serviço fornece um e você desenvolve offline
API real com uma conta de teste O verdadeiro original Credenciais, limite e saldo Verifica-se o caminho principal de ponta a ponta
Proxy de interceção A sua aplicação em execução em URLs reais, incluindo novas tentativas do SDK e cabeçalhos de resposta Definições de proxy e confiança nos certificados Teste falhas, limites e latência sem alterar a sua aplicação

Precisas de mais do que 1 destes. Os stubs mantêm os testes unitários rápidos. Um proxy mostra como toda a aplicação se comporta quando a API real falha. Para saber mais sobre como os dois se encaixam, veja Dev Proxy vs testes unitários.

O que os agentes de programação constroem

Quando pede a um agente de código para fazer com que a sua aplicação lide com falhas da API e demonstrar que isso funciona, ele escolhe um substituto por si. Queríamos saber qual, por isso fizemos um teste com 3 agentes de codificação (210 execuções). As tarefas usavam formulações como "trate corretamente a limitação de débito e mostra-me que funciona", "verifica-o sem gastar dinheiro em chamadas reais à API" e "executa isto sem uma chave da OpenAI ou ligação à Internet".

  • Em 76% das 140 execuções que pediam código executável, o agente recriou manualmente a falha: stubs de fetch, httpx.MockTransport, ou um servidor HTTP temporário.
  • Em 61 das 105 execuções em aplicações que chamam GitHub, OpenAI ou uma API meteorológica, o agente adicionou uma URL base ou um switch de configuração à aplicação para que esta pudesse aceder ao seu serviço simulado.
  • Nas 75 execuções em que a API real estava disponível e o prompt não a descartou, 0 testaram a aplicação no URL real da API.

Os stubs são uma escolha razoável para testes unitários. A lacuna é o que eles deixam de fora. O stub do agente devolve o erro que o agente esperava, que pode não corresponder ao que a API envia. E a opção que adicionou para aceder às naves falsas com a tua aplicação.

Como trabalhar com os testes do seu agente

  • Guarda os esboços para a tua lógica. São rápidos e testam as ramificações que o agente escreveu.
  • Pedir o formato real do erro. Peça ao agente para basear cada erro simulado nos códigos de estado, cabeçalhos e campos do corpo documentados pelo fornecedor. Um 429 básico não testa se a tua aplicação lê retry-after nem mostra um erro de faturação a partir de um limite de tarifa.
  • Opções de revisão adicionadas para os testes. Se o agente adicionar uma definição de URL base apenas para que os testes possam aceder a um mock, decide se queres essa definição no teu código de produção.
  • Executa a aplicação uma vez em URLs reais com falhas simuladas. Antes de enviares, verifica o que a aplicação em execução, o seu SDK e a sua política de retentativas fazem com os próprios erros da API. Para rever o tratamento de erros do agente passo a passo, veja Como verificar o tratamento de erros que o seu agente de codificação escreveu.

Experimente na sua app

Dev Proxy é um proxy de interceção para desenvolvimento. Devolve as respostas que definir para os URL a que a sua aplicação já acede, sem alterações no código da sua aplicação. Ativa o MockResponsePlugin na tua configuração, devproxyrc.json:

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
  "plugins": [
    {
      "name": "MockResponsePlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "mocksPlugin"
    }
  ],
  "urlsToWatch": [
    "https://api.contoso.com/*"
  ],
  "mocksPlugin": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/mockresponseplugin.schema.json",
    "mocksFile": "mocks.json"
  }
}

Então defina a resposta em mocks.json. Este retorna 503 com um Retry-After cabeçalho para o endpoint da previsão:

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/mockresponseplugin.mocksfile.schema.json",
  "mocks": [
    {
      "request": {
        "url": "https://api.contoso.com/v1/forecast*",
        "method": "GET"
      },
      "response": {
        "statusCode": 503,
        "headers": [
          {
            "name": "Retry-After",
            "value": "10"
          }
        ],
        "body": {
          "error": "Service unavailable"
        }
      }
    }
  ]
}

Inicie o Dev Proxy e execute a sua aplicação normalmente:

devproxy --config-file devproxyrc.json

Pedidos que não correspondem a um mock vão para a API real. Quando precisa de um backend que ainda não existe, o CrudApiPlugin simula uma API CRUD com dados em memória. Para fazer falhar uma parte dos pedidos aleatoriamente em vez de sempre, veja Testar a minha aplicação com erros aleatórios. Para instalar Dev Proxy, consulte Configurar Dev Proxy.

Passos seguintes

Ver também