1

Como rodar o WireMock em um container Docker (sem complicação)

Bom, eu estava fazendo o desafio backend do PicPay em Spring Boot e precisava simular serviços externos de autorização e notificação. O problema é que, observando o repositório do desafio, eu percebi que os links disponibilizados para simular esses serviços viviam quebrando, ficando offline ou simplesmente parando de funcionar do nada.

Então comecei a procurar uma forma de contornar isso e percebi que poderia mockar essas chamadas externas localmente. Basicamente, simular os endpoints como se a aplicação estivesse conversando com o serviço real.

Como eu já estava usando Docker para subir o banco de dados da aplicação, pensei:

“Por que não adicionar mais um container pra isso também?”

Além de resolver o problema, ainda seria uma boa oportunidade pra praticar mais Docker no processo.

Só que aí veio outro problema...

Praticamente todo tutorial que eu encontrava sobre WireMock com Docker:

  • era antigo
  • misturava várias formas diferentes de uso
  • não explicava a estrutura dos arquivos
  • assumia que você já entendia Docker
  • ou simplesmente jogava um monte de configuração sem explicar muita coisa

Então resolvi documentar aqui a forma mais simples que encontrei pra subir tudo usando containers.


Por que usar o WireMock?

Então, essa é uma boa pergunta na verdade 😄.

Quando comecei a pesquisar formas de mockar chamadas HTTP externas, eu percebi que existiam várias ferramentas diferentes pra resolver esse problema.

As que eu mais encontrei foram:

  • MockServer
  • Rest Assured
  • Restito
  • e o próprio WireMock

No começo eu achei que todas faziam praticamente a mesma coisa. E, sendo bem sincero, até fazem em alguns cenários.

Mas conforme fui lendo a documentação e testando algumas abordagens, comecei a perceber que cada uma resolve problemas um pouco diferentes.


MockServer

O MockServer me pareceu uma solução bem poderosa e flexível, principalmente pra cenários mais complexos.

Ele permite:

  • mockar HTTP e HTTPS
  • validar requests
  • criar expectativas mais avançadas
  • rodar em container facilmente

Mas, pra minha necessidade naquele momento, achei a configuração um pouco mais verbosa do que eu precisava.


Rest Assured

O Rest Assured aparece MUITO quando o assunto é teste de APIs em Java.

Só que ele é mais focado em testes automatizados de APIs do que em simular um serviço HTTP rodando separadamente.

Então, apesar de ser excelente pra testes, ele não era exatamente o que eu queria naquele cenário.


Restito

O Restito foi uma ferramenta que achei interessante porque ela é bem simples e direta.

Mas eu senti falta de:

  • mais exemplos modernos
  • comunidade maior
  • mais conteúdos usando Docker

Então por que escolhi o WireMock?

No final, acabei escolhendo o WireMock porque ele tinha exatamente o equilíbrio que eu estava procurando:

  • simples de subir com Docker
  • configuração relativamente fácil
  • muito usado pela indústria
  • bastante material da comunidade
  • suporte muito bom pra mockar APIs REST

Além disso, gostei bastante da estrutura baseada em arquivos JSON, já que fica fácil visualizar os endpoints mockados e versionar tudo junto do projeto.

E como meu objetivo era simular serviços externos do desafio do PicPay da forma mais simples possível, ele acabou encaixando perfeitamente.


O que vamos fazer

Pra ficar mais fácil de acompanhar, vou dividir esse processo em 3 partes:

  • Parte I → Subindo o WireMock com Docker
  • Parte II → Criando os endpoints mockados
  • Parte III → Integrando com a aplicação Spring

Parte I: Mão na massa

Primeiro você precisa criar um arquivo docker-compose.yaml.

É nele que vamos definir:

  • qual imagem o Docker vai baixar
  • nome do container
  • portas
  • volumes
  • e outras configurações do serviço

Para subir o WireMock, o compose fica mais ou menos assim:

services:
  wiremock:
    image: wiremock/wiremock:3.13.2
    container_name: my_wiremock

    ports:
      - "8089:8080"

    volumes:
      - ./wiremock:/home/wiremock

Se você já conhece um pouco de Docker, pode pular essa explicação sem problemas 😄.

Agora entendendo cada parte:

image

Aqui estamos dizendo qual imagem o Docker deve usar.

image: wiremock/wiremock:3.13.2

Se essa imagem não existir localmente, o Docker vai baixá-la automaticamente do Docker Hub.


container_name

container_name: my_wiremock

Define o nome do container.

Isso facilita bastante na hora de:

  • visualizar containers
  • acessar logs
  • executar comandos

ports

ports:
  - "8089:8080"

Aqui estamos fazendo um mapeamento de portas:

porta_da_maquina:porta_do_container

Ou seja:

  • tudo que acessar a porta 8089 da sua máquina
  • será redirecionado para a porta 8080 dentro do container

Então o WireMock ficará acessível em:

http://localhost:8089

volumes

volumes:
  - ./wiremock:/home/wiremock

Aqui estamos criando um volume entre:

  • a pasta wiremock da nossa máquina
  • e a pasta /home/wiremock dentro do container

Isso é importante porque o WireMock lê os arquivos de configuração diretamente desse diretório.

Na prática, isso permite:

  • editar mappings localmente
  • versionar os mocks no Git
  • não perder configurações ao reiniciar o container

Agora basta executar:

docker compose up -d

E pronto 🚀!!

Seu container do WireMock já estará rodando.


Para verificar se deu tudo certo, você pode executar:

docker ps

Esse comando mostra todos os containers que estão rodando atualmente.

Se você usa o Docker Desktop, também pode visualizar:

  • containers na aba Containers
  • imagens na aba Images

Além disso, você pode acessar no navegador:

http://localhost:8089/__admin

Se a interface administrativa do WireMock aparecer:

✅ deu tudo certo.


Parte II: Criando os mocks

Depois de executar:

docker compose up -d

você terá uma estrutura parecida com essa:

aplicacao-java/
├── gradle/
├── docker-compose.yml
├── src/
│   ├── main/
│   └── test/
└── wiremock/
    ├── mappings/
    └── __files/

O que significa cada pasta?

  • mappings/

    Aqui ficam os arquivos .json responsáveis por definir os endpoints mockados.

  • __files/

    Pasta usada para armazenar arquivos auxiliares, como responses maiores, templates e payloads externos.

    Em cenários simples, ela geralmente é opcional.


Agora vamos criar nosso primeiro endpoint mockado dentro da pasta mappings.

Exemplo:

{
  "request": {
    "method": "GET",
    "urlPath": "/api/v1/authorize",
    "queryParameters": {
      "scenario": {
        "equalTo": "success"
      }
    }
  },
  "response": {
    "status": 200,
    "jsonBody": {
      "status": "success",
      "data": {
        "authorization": true
      }
    },
    "headers": {
      "Content-Type": "application/json"
    }
  }
}

O que está acontecendo aqui?

Por causa dessa configuração no docker-compose.yml:

volumes:
  - ./wiremock:/home/wiremock

o container passa a enxergar a pasta local:

./wiremock

como:

/home/wiremock

dentro dele.

E o WireMock, por padrão, procura automaticamente os mappings em:

/home/wiremock/mappings

Ou seja, ele:

  • encontra os arquivos .json
  • carrega os endpoints automaticamente
  • disponibiliza as rotas mockadas

Na maioria dos casos o WireMock detecta mudanças automaticamente nos mappings.

Mas, caso algum endpoint novo não apareça imediatamente, você pode reiniciar o container com:

docker compose restart

Testando pra ver se deu certo

Você pode ir no terminal e rodar o comando abaixo, ou simplesmente acessar esse link no navegador:

curl "http://localhost:8089/api/v1/authorize?scenario=success"

Nos dois casos será retornado algo assim:

{
  "status": "success",
  "data": {
    "authorization": true
  }
}

Se quiser visualizar melhor a resposta formatada no terminal:

curl "http://localhost:8089/api/v1/authorize?scenario=success" | jq

E aqui vem a parte interessante.

Talvez você esteja se perguntando:

“Como o WireMock sabe exatamente o que retornar?”

Porque foi exatamente isso que definimos no arquivo .json 😄

Perceba que nem existe backend Java rodando nesse momento. Quem está respondendo tudo isso é somente o WireMock.

E ele faz isso baseado em duas partes principais:

  • request
  • response

request section

"request": {
  "method": "GET",
  "urlPath": "/api/v1/authorize"
}

Isso significa:

quando alguém fizer um GET para essa rota

response section

"response": {
  "status": 200
}

Isso significa:

responda com status HTTP 200

queryParameters

"queryParameters": {
  "scenario": {
    "equalTo": "success"
  }
}

Isso significa:

a query parameter precisa conter ?scenario=success

Ou seja, o endpoint só será acionado corretamente se a URL for:

/api/v1/authorize?scenario=success

Parte III: Integrando com a aplicação Spring

Agora que já conseguimos acessar as URLs do nosso mini servidor mockado, podemos conectar ele ao código Java da aplicação.

Bom, você pode fazer isso de duas maneiras diferentes.


Opção 1: Configurando no application.yml

external:
  authorization:
    url: http://localhost:8089/api/v1/authorize

  notification:
    url: http://localhost:8089/api/v1/notify

E depois acessando no código:

@Value("${external.authorization.url}")
private String authorizationUrl;

Essa abordagem é legal porque deixa as URLs centralizadas e facilita trocar ambientes futuramente.


Opção 2: URL direto no código

Você também pode simplesmente salvar a URL em uma variável:

String url = "http://localhost:8089/api/v1/authorize";

Para cenários simples isso funciona tranquilamente também.


Como falei no começo do artigo, o desafio do PicPay possuía duas integrações externas:

  • autorização
  • notificação

Então precisei criar tanto cenários de sucesso quanto de falha para cada uma delas.

Minha estrutura final ficou assim:

wiremock/
├── mappings/
│   ├── authorize-success.json
│   ├── authorize-fail.json
│   ├── notify-success.json
│   └── notify-fail.json
└── __files/

Depois de estruturar tudo assim, eu consegui desenvolver e testar minha aplicação sem depender dos endpoints externos do desafio.

Além disso, ficou muito mais fácil:

  • simular falhas
  • testar cenários específicos
  • desenvolver offline
  • manter os mocks versionados junto do projeto

Conclusão

No final das contas, o WireMock resolveu exatamente o problema que eu tinha:
parar de depender de APIs externas instáveis durante o desenvolvimento. E, cara, sinceramente? Depois que você entende a estrutura básica dele, o WireMock deixa de parecer complicado e vira uma ferramenta extremamente útil no dia a dia de backend.

Principalmente quando você começa a trabalhar com:

  • microsserviços
  • integrações externas
  • testes de integração
  • ambientes isolados

Se você chegou até aqui, espero que esse artigo tenha conseguido te poupar as mesmas dores de cabeça que eu tive procurando documentação 😄. Vou deixar nas referências alguns dos artigos que usei durante o desenvolvimento do desafio e na escrita desse artigo.


Referências

Carregando publicação patrocinada...