a9dea19531
Introduce health checking functionality with liveness and readiness endpoints to monitor the application's status. Implement a health checker that verifies database connectivity and provides a simple liveness check. Update service routing to use the new health checker functionality. Add corresponding unit tests for validation.
76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
package health
|
|
|
|
import (
|
|
"database/sql"
|
|
"log/slog"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/DATA-DOG/go-sqlmock"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestLivenessHandler(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
db, _, err := sqlmock.New()
|
|
require.NoError(t, err)
|
|
defer db.Close()
|
|
|
|
checker := New(db, logger)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/health/live", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
checker.LivenessHandler(rec, req)
|
|
|
|
assert.Equal(t, http.StatusOK, rec.Code)
|
|
assert.Contains(t, rec.Body.String(), `"status":"UP"`)
|
|
}
|
|
|
|
func TestReadinessHandler_Healthy(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
db, mock, err := sqlmock.New(sqlmock.MonitorPingsOption(true))
|
|
require.NoError(t, err)
|
|
defer db.Close()
|
|
|
|
// Expect a ping and return success
|
|
mock.ExpectPing().WillReturnError(nil)
|
|
|
|
checker := New(db, logger)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/health/ready", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
checker.ReadinessHandler(rec, req)
|
|
|
|
assert.Equal(t, http.StatusOK, rec.Code)
|
|
assert.Contains(t, rec.Body.String(), `"status":"UP"`)
|
|
assert.Contains(t, rec.Body.String(), `"database":"UP"`)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|
|
|
|
func TestReadinessHandler_DatabaseDown(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
db, mock, err := sqlmock.New(sqlmock.MonitorPingsOption(true))
|
|
require.NoError(t, err)
|
|
defer db.Close()
|
|
|
|
// Expect a ping and return error
|
|
mock.ExpectPing().WillReturnError(sql.ErrConnDone)
|
|
|
|
checker := New(db, logger)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/health/ready", nil)
|
|
rec := httptest.NewRecorder()
|
|
|
|
checker.ReadinessHandler(rec, req)
|
|
|
|
assert.Equal(t, http.StatusServiceUnavailable, rec.Code)
|
|
assert.Contains(t, rec.Body.String(), `"status":"DOWN"`)
|
|
assert.Contains(t, rec.Body.String(), `"database":"DOWN"`)
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
|
}
|