Testando Código Que Aceita context.Context
Funções que aceitam context.Context precisam de testes para sucesso, deadline excedido e cancelamento manual - não apenas o caminho feliz.
Busque em todas as páginas da documentação
Funções que aceitam context.Context precisam de testes para sucesso, deadline excedido e cancelamento manual - não apenas o caminho feliz.
O pacote context do Go e os helpers de testing tornam esses caminhos determinísticos sem dormir em CI.
Use context.WithTimeout ou WithCancel em testes para gerar resultados de ctx.Err().
Prefira fakes baseados em canais em vez de time.Sleep ao testar a propagação de cancelamento.
Asserte com errors.Is para context.Canceled e context.DeadlineExceeded.
Cartão de receita de referência rápida - pronto para copiar e colar.
func TestWorkCanceled(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
err := Work(ctx)
if !errors.Is(err, context.Canceled) {
t.Fatalf("got %v, want Canceled", err)
}
}Quando usar isso:
ctx juntamente com entradas normais.httptest e contextos de requisição.package work_test
import (
"context"
"errors"
"testing"
"time"
"example.com/ctxdemo/work"
)
func TestFetchDeadline(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond)
defer cancel()
err := work.Fetch(ctx, slowStub{})
if !errors.Is(err, context.DeadlineExceeded) {
t.Fatalf("got %v", err)
}
}
func TestFetchCancel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(5 * time.Millisecond)
cancel()
}()
err := work.Fetch(ctx, slowStub{})
if !errors.Is(err, context.Canceled) {
t.Fatalf("got %v", err)
}
}
type slowStub struct{}
func (slowStub) Run(ctx context.Context) error {
select {
case <-time.After(200 * time.Millisecond):
return nil
case <-ctx.Done():
return ctx.Err()
}
}O que isso demonstra:
DeadlineExceeded de um WithTimeout curto sem sleeps longos no caminho de asserção.cancel() manual de outra goroutine simula desconexão do cliente.ctx da mesma forma que I/O de produção faria.errors.Is mantém as asserções estáveis se os erros forem encapsulados com %w.t.Context() (Go 1.24+) fornece um contexto cancelado quando o teste termina - útil para testes de integração.httptest.NewRequest anexa um contexto de background; substitua por req.WithContext(ctx) para casos de cancelamento.| Cenário | Configuração | Esperado |
|---|---|---|
| Sucesso | context.Background() | erro nil |
| Timeout | WithTimeout(..., 1ms) | DeadlineExceeded |
| Cancelamento manual | cancel() antes da chamada | Canceled |
| Pai cancelado | cancela o pai do filho | Err() do filho definido |
| Causa anexada | WithCancelCause | context.Cause(ctx) |
req := httptest.NewRequest(http.MethodGet, "/", nil)
ctx, cancel := context.WithCancel(req.Context())
cancel()
req = req.WithContext(ctx)
rec := httptest.NewRecorder()
handler(rec, req)
// esperar nenhum corpo de resposta em caso de cancelamentofunc wait(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
defer timer.Stop()
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
return nil
}
}Sempre pare os timers em testes e produção para evitar vazamentos.
cancel() imediato ou timeouts de 1-20ms.==. Correção: errors.Is e errors.As.-race. Correção: sempre use defer cancel().WithContext.cancel(). Correção: contexto por subteste com cuidado em t.Parallel().| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
t.Context() | Limpeza automática ao final do teste | Controle de tempo de cancelamento granular |
| Fake de interface com canal bloqueante | Cancelamento determinístico | Funções puras simples |
| Teste de integração com DB real | Verificação de cancelamento do driver | Testes de lógica de nível de unidade |
testing/quick | Fuzzing de deadline aleatório | Testes de tabela legíveis |
time.Sleep em testes | Nunca preferível | - |
Teste funções que ramificam em ctx.Done() ou passam ctx para dependências.
Helpers puros que apenas encaminham ctx podem confiar em testes de integração.
Anexe valores na configuração do teste com os mesmos helpers de chave que a produção usa.
Assegure que os acessadores retornam os metadados esperados.
Sim - assert.ErrorIs(t, err, context.Canceled) é uma boa leitura em testes de tabela.
Construa um contexto com timeout e invoque o interceptador com httptest ou buffers de teste do grpc.
Verifique o mapeamento de codes.DeadlineExceeded.
Cancele com WithCancelCause e assevere errors.Is(context.Cause(ctx), wantCause).
Use context.Background() a menos que esteja benchmarkando especificamente o overhead de cancelamento.
Relate -benchmem separadamente dos testes de cancelamento.
Sempre use defer cancel() para WithTimeout e pare timers em loops select.
Construa um novo ctx por linha dentro de t.Run para evitar poluição entre testes.
Cancele o pai, derive context.WithoutCancel(parent) e assevere que o filho ainda executa brevemente.
Verifique se os valores do pai são visíveis.
Sim - execute testes de cancelamento com -race para capturar goroutines que ignoram Done().
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: 18 de jul. de 2026