testify, httptest & Test Doubles
Asserções, testes de manipuladores HTTP e mocks de interface.
Busque em todas as páginas da documentação
Asserções, testes de manipuladores HTTP e mocks de interface.
A biblioteca padrão cobre a execução de testes e a gravação de respostas HTTP.
testify adiciona falhas de asserção legíveis; httptest é stdlib para manipuladores; test doubles em Go são geralmente fakes escritos à mão por trás de interfaces pequenas.
Cartão de referência rápida - pronto para copiar e colar.
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
)
func TestHandler(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/health", nil)
rec := httptest.NewRecorder()
HealthHandler(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
require.JSONEq(t, `{"status":"ok"}`, rec.Body.String())
}Quando usar isso:
ListenAndServerequire pare a configuração após uma pré-condição falhapackage api
import (
"context"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var ErrNotFound = errors.New("não encontrado")
type UserStore interface {
Get(ctx context.Context, id string) (string, error)
}
type fakeStore struct {
users map[string]string
}
func (f *fakeStore) Get(ctx context.Context, id string) (string, error) {
if name, ok := f.users[id]; ok {
return name, nil
}
return "", ErrNotFound
}
func UserHandler(store UserStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
name, err := store.Get(r.Context(), id)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
_ = json.NewEncoder(w).Encode(map[string]string{"name": name})
}
}
func TestUserHandler(t *testing.T) {
store := &fakeStore{users: map[string]string{"1": "Ada"}}
srv := httptest.NewServer(UserHandler(store))
t.Cleanup(srv.Close)
resp, err := http.Get(srv.URL + "?id=1")
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode)
var body map[string]string
require.NoError(t, json.NewDecoder(resp.Body).Decode(&body))
assert.Equal(t, "Ada", body["name"])
}O que isso demonstra:
fakeStore implementa UserStore sem um gerador de mockhttptest.NewServer exercita o comportamento real do http.Clientt.Cleanup fecha o servidor após o testerequire) de verificações extras (assert)httptest.NewRecorder implementa http.ResponseWriter em memória.httptest.NewServer vincula 127.0.0.1:0 e retorna uma URL pronta para o cliente.reflect.DeepEqual e formata diffs.| Ferramenta | Inicia listener | Melhor para |
|---|---|---|
NewRecorder | Não | Testes unitários de funções manipuladoras |
NewServer | Sim (loopback) | Cadeias de middleware, TLS, timeouts do cliente |
httptest.NewRequest | Não | Construindo *http.Request com contexto |
// gomock (opcional): go.uber.org/mock/mockgen
// Gerar: mockgen -destination=mocks/store_mock.go . UserStoreFakes escritos à mão permanecem legíveis para um ou dois métodos; geradores ajudam interfaces amplas.
-count=100. Correção: defer resp.Body.Close() após cada chamada do cliente.require.JSONEq ou decodifique em structs.suite.Suite compartilha campos entre testes. Correção: Prefira TestXxx simples com tabelas, a menos que hooks sejam essenciais.req = req.WithContext(ctx) na configuração.| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
if got != want Simples | Zero dependências, pacotes minúsculos | Comparações de struct grandes |
cmp.Diff (google/go-cmp) | Diffs de struct precisos sem testify | Equipe já padronizada em testify |
go.uber.org/mock | Interfaces amplas, muitas implementações | Fakes de um método |
| Banco de dados docker real (testcontainers) | Verdade de integração SQL | Testando mapeamento JSON de manipulador unitariamente |
Não.
Muitas bases de código usam apenas verificações stdlib; testify é um módulo de conveniência.
require chama t.FailNow() - use para pré-condições de configuração.
assert registra a falha e continua - use para múltiplas expectativas independentes.
Envolva um manipulador stub com seu middleware, passe httptest.NewRecorder e afirme o gravador.
Para testes de cadeia completa, use NewServer.
Sim - monte rotas em um http.Handler ou chame ServeHTTP do framework com um gravador.
Objetos de contexto do framework podem precisar de seus helpers de teste.
Mantenha fakes pequenos em _test.go.
Mova fakes compartilhados para export_test.go ou um pacote internal/testutil se muitos pacotes os reutilizarem.
Adicione campos na struct fake (failNext bool, err error) alternados por linha de tabela.
Sim - cada subteste recebe seu próprio *testing.T.
Evite compartilhar fakes mutáveis entre subtestes paralelos sem sincronização.
Use bufconn com um listener em memória ou mocks gerados para o stub do cliente.
Veja a seção grpc-protobuf para padrões.
Arquivos Golden em testdata/ são o snapshot idiomático do Go.
Snapshots testify são menos comuns do que JSONEq mais fixtures.
Sim para código de cliente que chama APIs externas - implemente RoundTrip em um fake.
Mantém os testes offline e determinísticos.
rec.Header().Get("Content-Type") em um gravador, ou resp.Header em respostas do cliente.
Use assert.ErrorIs e assert.ErrorAs - eles envolvem errors.Is / errors.As.
Versões de Stack: Esta página foi escrita para Go 1.26.x (padrão GC Green Tea, go fix modernizers - verifique o patch na compilação), chi (última - verifique na compilação), gin (última - verifique na compilação), echo (última - verifique na compilação), google.golang.org/grpc (última - verifique na compilação), sigs.k8s.io/controller-runtime (última - verifique na compilação), kubebuilder (última - verifique na compilação), tinygo (última - verifique os alvos de placa na compilação), wazero (última - verifique na compilação) e golangci-lint (última - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026