Documentation
¶
Overview ¶
Package testutil provides testing helpers for HTTP handlers and tygor RPC handlers. This package is designed to be import-cycle safe and can be used from any package.
Index ¶
- func AssertHeader(t *testing.T, w *httptest.ResponseRecorder, key, expectedValue string)
- func AssertJSONResponse(t *testing.T, w *httptest.ResponseRecorder, expected any)
- func AssertStatus(t *testing.T, w *httptest.ResponseRecorder, expectedStatus int)
- func DecodeJSON(t *testing.T, w *httptest.ResponseRecorder, v any)
- type ContextSetupFunc
- type ErrorResponse
- type RequestBuilder
- func (b *RequestBuilder) Build() (*http.Request, *httptest.ResponseRecorder)
- func (b *RequestBuilder) GET(path string) *RequestBuilder
- func (b *RequestBuilder) POST(path string) *RequestBuilder
- func (b *RequestBuilder) WithBody(body string) *RequestBuilder
- func (b *RequestBuilder) WithHeader(key, value string) *RequestBuilder
- func (b *RequestBuilder) WithJSON(v any) *RequestBuilder
- func (b *RequestBuilder) WithQuery(key, value string) *RequestBuilder
- func (b *RequestBuilder) WithRPCInfo(service, method string) *RequestBuilder
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssertHeader ¶
func AssertHeader(t *testing.T, w *httptest.ResponseRecorder, key, expectedValue string)
AssertHeader checks that a response header has the expected value.
func AssertJSONResponse ¶
func AssertJSONResponse(t *testing.T, w *httptest.ResponseRecorder, expected any)
AssertJSONResponse decodes the response body and compares it with expected value. Expects the response to be wrapped in {"result": ...} envelope.
func AssertStatus ¶
func AssertStatus(t *testing.T, w *httptest.ResponseRecorder, expectedStatus int)
AssertStatus checks that the response has the expected status code.
func DecodeJSON ¶
func DecodeJSON(t *testing.T, w *httptest.ResponseRecorder, v any)
DecodeJSON decodes the response body into the provided value.
Types ¶
type ContextSetupFunc ¶
type ContextSetupFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, service, method string) context.Context
ContextSetupFunc is a function that sets up the request context. It receives the current context, response writer, and request, and returns a new context.
type ErrorResponse ¶
type ErrorResponse struct {
Code string `json:"code"`
Message string `json:"message"`
Details map[string]any `json:"details,omitempty"`
}
ErrorResponse represents a generic error response with code and message.
func AssertJSONError ¶
func AssertJSONError(t *testing.T, w *httptest.ResponseRecorder, expectedCode string) *ErrorResponse
AssertJSONError checks that the response contains an error with the expected code. Expects the error to be wrapped in {"error": {...}} envelope.
type RequestBuilder ¶
type RequestBuilder struct {
// contains filtered or unexported fields
}
RequestBuilder helps construct test HTTP requests with fluent API.
Example (Comparison) ¶
Example showing the before/after comparison
package main
import (
"context"
"net/http"
"github.com/broady/tygor"
"github.com/broady/tygor/testutil"
)
// Example types for testing
type ExampleRequest struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
}
type ExampleResponse struct {
Message string `json:"message"`
ID int `json:"id"`
}
// Example handler function
func exampleHandler(ctx context.Context, req *ExampleRequest) (*ExampleResponse, error) {
return &ExampleResponse{
Message: "Hello, " + req.Name,
ID: 123,
}, nil
}
func main() {
// BEFORE (manual setup - verbose):
// reqBody := `{"name":"Alice","email":"alice@example.com"}`
// req := httptest.NewRequest("POST", "/test", strings.NewReader(reqBody))
// req.Header.Set("Content-Type", "application/json")
// info := &tygor.RPCInfo{Service: "TestService", Method: "TestMethod"}
// w := httptest.NewRecorder()
// ctx := tygor.NewTestContext(req.Context(), w, req, info)
// req = req.WithContext(ctx)
// config := tygor.HandlerConfig{}
// handler.ServeHTTP(w, req, config)
// AFTER (using testutil - more concise):
handler := tygor.Unary(exampleHandler)
req, w := testutil.NewRequest(tygor.TestContextSetup()).
POST("/test").
WithJSON(&ExampleRequest{Name: "Alice", Email: "alice@example.com"}).
Build()
handler.ServeHTTP(w, req, tygor.HandlerConfig{})
testutil.AssertStatus(nil, w, http.StatusOK)
}
func NewRequest ¶
func NewRequest(contextSetup ...ContextSetupFunc) *RequestBuilder
NewRequest creates a new request builder. Optionally accepts a ContextSetupFunc to configure the request context.
func (*RequestBuilder) Build ¶
func (b *RequestBuilder) Build() (*http.Request, *httptest.ResponseRecorder)
Build creates the HTTP request and ResponseRecorder. Uses the contextSetup provided to NewRequest().
func (*RequestBuilder) GET ¶
func (b *RequestBuilder) GET(path string) *RequestBuilder
GET sets the HTTP method to GET.
func (*RequestBuilder) POST ¶
func (b *RequestBuilder) POST(path string) *RequestBuilder
POST sets the HTTP method to POST.
func (*RequestBuilder) WithBody ¶
func (b *RequestBuilder) WithBody(body string) *RequestBuilder
WithBody sets the raw request body.
func (*RequestBuilder) WithHeader ¶
func (b *RequestBuilder) WithHeader(key, value string) *RequestBuilder
WithHeader adds a header to the request.
func (*RequestBuilder) WithJSON ¶
func (b *RequestBuilder) WithJSON(v any) *RequestBuilder
WithJSON sets the request body as JSON.
func (*RequestBuilder) WithQuery ¶
func (b *RequestBuilder) WithQuery(key, value string) *RequestBuilder
WithQuery adds a query parameter.
func (*RequestBuilder) WithRPCInfo ¶
func (b *RequestBuilder) WithRPCInfo(service, method string) *RequestBuilder
WithRPCInfo sets the service and method for RPC context.