-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: Add coverage for healthcheck server #37
Changes from 1 commit
573013d
c873399
4cc37c8
217f578
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,166 @@ | ||||||||||||
package http | ||||||||||||
|
||||||||||||
import ( | ||||||||||||
"encoding/json" | ||||||||||||
"fmt" | ||||||||||||
"net/http" | ||||||||||||
"net/http/httptest" | ||||||||||||
"os" | ||||||||||||
"testing" | ||||||||||||
) | ||||||||||||
|
||||||||||||
func TestHealthCheckHandler(t *testing.T) { | ||||||||||||
tests := []struct { | ||||||||||||
name string | ||||||||||||
method string | ||||||||||||
expectedStatus int | ||||||||||||
wantBody bool | ||||||||||||
}{ | ||||||||||||
{ | ||||||||||||
name: "GET request returns 200 and status ok", | ||||||||||||
method: http.MethodGet, | ||||||||||||
expectedStatus: http.StatusOK, | ||||||||||||
wantBody: true, | ||||||||||||
}, | ||||||||||||
{ | ||||||||||||
name: "POST request returns 405 and status not allowed", | ||||||||||||
method: http.MethodPost, | ||||||||||||
expectedStatus: http.StatusMethodNotAllowed, | ||||||||||||
wantBody: false, | ||||||||||||
}, | ||||||||||||
} | ||||||||||||
|
||||||||||||
for _, tt := range tests { | ||||||||||||
t.Run(tt.name, func(t *testing.T) { | ||||||||||||
req := httptest.NewRequest(tt.method, "/healthz", nil) | ||||||||||||
w := httptest.NewRecorder() | ||||||||||||
|
||||||||||||
handleHealthCheck(w, req) | ||||||||||||
|
||||||||||||
if got := w.Code; got != tt.expectedStatus { | ||||||||||||
t.Errorf("handleHealthCheck() status = %v, want %v", got, tt.expectedStatus) | ||||||||||||
} | ||||||||||||
|
||||||||||||
if tt.wantBody { | ||||||||||||
var response struct { | ||||||||||||
Status string `json:"status"` | ||||||||||||
} | ||||||||||||
|
||||||||||||
if err := json.NewDecoder(w.Body).Decode(&response); err != nil { | ||||||||||||
t.Errorf("failed to decode response body: %v", err) | ||||||||||||
} | ||||||||||||
Comment on lines
+48
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And this would be
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||
|
||||||||||||
if response.Status != "ok" { | ||||||||||||
t.Errorf("handleHealthCheck() status = %v, want %v", response.Status, "ok") | ||||||||||||
} | ||||||||||||
|
||||||||||||
if contentType := w.Header().Get("Content-Type"); contentType != "application/json" { | ||||||||||||
t.Errorf("handleHealthCheck() Content-Type = %v, want %v", contentType, "application/json") | ||||||||||||
} | ||||||||||||
} | ||||||||||||
}) | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
func TestHealthCheckHandlerEncodingError(t *testing.T) { | ||||||||||||
req := httptest.NewRequest(http.MethodGet, "/healthz", nil) | ||||||||||||
|
||||||||||||
failingWriter := &failingWriter{ | ||||||||||||
headers: http.Header{}, | ||||||||||||
} | ||||||||||||
handleHealthCheck(failingWriter, req) | ||||||||||||
|
||||||||||||
if failingWriter.statusCode != http.StatusInternalServerError { | ||||||||||||
t.Errorf("handleHealthCheck() with encoding error, status = %v, want %v", | ||||||||||||
failingWriter.statusCode, http.StatusInternalServerError) | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
type failingWriter struct { | ||||||||||||
statusCode int | ||||||||||||
headers http.Header | ||||||||||||
} | ||||||||||||
|
||||||||||||
func (w *failingWriter) Header() http.Header { | ||||||||||||
return w.headers | ||||||||||||
} | ||||||||||||
|
||||||||||||
func (w *failingWriter) Write([]byte) (int, error) { | ||||||||||||
return 0, fmt.Errorf("encoding error") | ||||||||||||
} | ||||||||||||
|
||||||||||||
func (w *failingWriter) WriteHeader(statusCode int) { | ||||||||||||
w.statusCode = statusCode | ||||||||||||
} | ||||||||||||
|
||||||||||||
func TestNewHealthCheckServer(t *testing.T) { | ||||||||||||
server := NewHealthCheckServer() | ||||||||||||
|
||||||||||||
if server == nil { | ||||||||||||
t.Fatal("NewHealthCheckServer() returned nil") | ||||||||||||
return | ||||||||||||
} | ||||||||||||
|
||||||||||||
if server.Addr != ":5680" { | ||||||||||||
t.Errorf("NewHealthCheckServer() addr = %v, want %v", server.Addr, ":5680") | ||||||||||||
} | ||||||||||||
|
||||||||||||
if server.ReadTimeout != readTimeout { | ||||||||||||
t.Errorf("NewHealthCheckServer() readTimeout = %v, want %v", server.ReadTimeout, readTimeout) | ||||||||||||
} | ||||||||||||
|
||||||||||||
if server.WriteTimeout != writeTimeout { | ||||||||||||
t.Errorf("NewHealthCheckServer() writeTimeout = %v, want %v", server.WriteTimeout, writeTimeout) | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
func TestGetPort(t *testing.T) { | ||||||||||||
tests := []struct { | ||||||||||||
name string | ||||||||||||
envPort string | ||||||||||||
expectedPort int | ||||||||||||
}{ | ||||||||||||
{ | ||||||||||||
name: "returns default port when env var is not set", | ||||||||||||
envPort: "", | ||||||||||||
expectedPort: defaultPort, | ||||||||||||
}, | ||||||||||||
{ | ||||||||||||
name: "returns custom port when valid env var is set", | ||||||||||||
envPort: "8080", | ||||||||||||
expectedPort: 8080, | ||||||||||||
}, | ||||||||||||
{ | ||||||||||||
name: "returns default port when env var is negative", | ||||||||||||
envPort: "-1", | ||||||||||||
expectedPort: defaultPort, | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wonder if we should throw instead if an invalid port is configured? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactored to move this to the new config style from n8n-io/n8n#8446 |
||||||||||||
}, | ||||||||||||
{ | ||||||||||||
name: "returns default port when env var is zero", | ||||||||||||
envPort: "0", | ||||||||||||
expectedPort: defaultPort, | ||||||||||||
}, | ||||||||||||
{ | ||||||||||||
name: "returns default port when env var is too large", | ||||||||||||
envPort: "65536", | ||||||||||||
expectedPort: defaultPort, | ||||||||||||
}, | ||||||||||||
{ | ||||||||||||
name: "returns default port when env var is not a number", | ||||||||||||
envPort: "invalid", | ||||||||||||
expectedPort: defaultPort, | ||||||||||||
}, | ||||||||||||
} | ||||||||||||
|
||||||||||||
for _, tt := range tests { | ||||||||||||
t.Run(tt.name, func(t *testing.T) { | ||||||||||||
os.Setenv(portEnvVar, tt.envPort) | ||||||||||||
|
||||||||||||
if got := GetPort(); got != tt.expectedPort { | ||||||||||||
t.Errorf("GetPort() = %v, want %v", got, tt.expectedPort) | ||||||||||||
} | ||||||||||||
|
||||||||||||
os.Unsetenv(portEnvVar) | ||||||||||||
}) | ||||||||||||
} | ||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comes a bit late to the party since most of the tests have already been written, but maybe we should use a package like
github.com/stretchr/testify/assert
to make these assertions clearer? E.g. this would then beThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I'll start using
testify
from now on and maybe later we can revisit older tests!