Контекст для тестов
Допустим, мы хотим протестировать этот жутко полезный сервер:
// Дает ответы на все вопросы.
type Server struct{}
// Возвращает ответ сервера.
func (s *Server) Get(query string) int {
return 42
}
// Запускает сервер. Остановка через отмену контекста.
func startServer(ctx context.Context) *Server {
go func() {
select {
case <-ctx.Done():
// Освобождаем ресурсы.
}
}()
return &Server{}
}
Вот чудесный тест, который я написал:
func Test(t *testing.T) {
srv := startServer(context.Background())
if srv.Get("how much?") != 42 {
t.Fatal("unexpected value")
}
}
Тест проходит, но есть проблемка: я использовал пустой контекст, так что на самом деле сервер не остановился. Такие утечки ресурсов могут стать проблемой — особенно если тестов много.
Исправить это несложно — достаточно использовать контекст с отменой:
func Test(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
srv := startServer(ctx)
if srv.Get("how much?") != 42 {
t.Fatal("unexpected value")
}
}
Но практика показывает, что люди часто забывают это делать 🤷♀️
Поэтому в Go 1.24 добавили метод T.Context
. Он возвращает контекст, который автоматически отменяется перед тем, как тест завершится:
func Test(t *testing.T) {
srv := startServer(t.Context())
if srv.Get("how much?") != 42 {
t.Fatal("unexpected value")
}
}
Удобно!
★ Подписывайтесь на новые заметки.