Documentation
¶
Overview ¶
Package mockaso provides a fluent API for creating HTTP mock servers in tests. It wraps Go's httptest.Server with a powerful stubbing system that supports request matching, pattern-based URLs, and flexible response configuration.
Basic Usage ¶
Create a server, add stubs, and use it in your tests:
server := mockaso.NewServer(mockaso.WithLogger(t))
server.MustStart()
defer server.MustShutdown()
server.Stub("GET", mockaso.Path("/users")).
Respond(mockaso.WithJSON([]User{{ID: 1, Name: "Alice"}}))
client := server.Client()
resp, _ := client.Get("/users") // Uses relative URL
Stub Matching ¶
Stubs are evaluated in the order they are added. The first matching stub handles the request. If no stub matches, the server returns status 666.
URL matching supports exact paths, regex patterns, and parameter extraction:
mockaso.Path("/users") // Exact path
mockaso.PathRegex(`/users/\d+`) // Regex
mockaso.PathPattern("/users/{id}") // Pattern with params
Additional matchers refine which requests a stub handles:
server.Stub("POST", mockaso.Path("/users")).
Match(
mockaso.MatchHeader("Content-Type", "application/json"),
mockaso.MatchJSONBody(expectedData),
).
Respond(mockaso.WithStatusCode(201))
Response Configuration ¶
Responses support JSON, custom headers, status codes, and delays:
stub.Respond(
mockaso.WithStatusCode(200),
mockaso.WithJSON(data),
mockaso.WithHeader("X-Custom", "value"),
mockaso.WithDelay(100 * time.Millisecond),
)
Index ¶
- type BodyMatcherMapFunc
- type BodyMatcherStringFunc
- type LogLogger
- type Logger
- type RequestMatcherFunc
- type Server
- func (s *Server) Clear()
- func (s *Server) Client() *http.Client
- func (s *Server) Logger() Logger
- func (s *Server) MustShutdown()
- func (s *Server) MustStart()
- func (s *Server) Shutdown() error
- func (s *Server) Start() error
- func (s *Server) Stub(method string, url URLMatcher) Stub
- func (s *Server) TestServer() *httptest.Server
- func (s *Server) URL() string
- type ServerOption
- type SlogLogger
- type Stub
- type StubMatcherRule
- func MatchBodyMapFunc(bodyMatcher BodyMatcherMapFunc) StubMatcherRule
- func MatchBodyStringFunc(bodyMatcher BodyMatcherStringFunc) StubMatcherRule
- func MatchHeader(key, value string) StubMatcherRule
- func MatchJSONBody(body any) StubMatcherRule
- func MatchNoBody() StubMatcherRule
- func MatchParam(key, value string) StubMatcherRule
- func MatchQuery(key, value string) StubMatcherRule
- func MatchRawJSONBody[T string | []byte | json.RawMessage](raw T) StubMatcherRule
- func MatchRequest(requestMatcher RequestMatcherFunc) StubMatcherRule
- type StubResponder
- type StubResponseRule
- func WithBody(body any) StubResponseRule
- func WithDelay(d time.Duration) StubResponseRule
- func WithHeader(key, value string) StubResponseRule
- func WithHeaders(headers map[string]string) StubResponseRule
- func WithJSON(body any) StubResponseRule
- func WithRawJSON[T string | []byte | json.RawMessage](raw T) StubResponseRule
- func WithStatusCode(statusCode int) StubResponseRule
- type URLMatcher
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BodyMatcherMapFunc ¶
BodyMatcherMapFunc is a function that validates an HTTP request body represented as a map. It receives the parsed JSON body and returns true if the request should match.
type BodyMatcherStringFunc ¶
BodyMatcherStringFunc is a function that validates an HTTP request body as a plain string. It receives the raw body content and returns true if the request should match.
type LogLogger ¶
type LogLogger struct {
// contains filtered or unexported fields
}
LogLogger implementation of Logger using a log.Logger. This is useful for integration with standard library logging or legacy code.
Example:
logger := log.New(os.Stdout, "[MOCKASO] ", log.LstdFlags) server := mockaso.NewServer(mockaso.WithLogLogger(logger))
func NewLogLogger ¶
NewLogLogger creates a new LogLogger wrapping the provided log.Logger.
type Logger ¶
Logger abstraction intended for use with testing.T. The interface is compatible with testing.T's Log and Logf methods, allowing test loggers to be used directly with mock servers.
Example with testing.T:
func TestAPI(t *testing.T) {
server := mockaso.NewServer(mockaso.WithLogger(t))
server.MustStart()
defer server.MustShutdown()
// Server will log to test output
}
type RequestMatcherFunc ¶
RequestMatcherFunc is a function that determines if an HTTP request matches specific criteria. It is used to create custom matchers with MatchRequest.
Example:
customMatcher := mockaso.RequestMatcherFunc(func(r *http.Request) bool {
return r.ContentLength > 1024
})
stub.Match(mockaso.MatchRequest(customMatcher))
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is a wrapper around httptest.Server that provides HTTP endpoint mocking capabilities with a fluent API for stubbing responses.
When no stub matches an incoming request, the server responds with status code 666 (demon code) and a descriptive error message.
Example:
server := mockaso.NewServer(mockaso.WithLogger(t))
server.MustStart()
defer server.MustShutdown()
server.Stub("GET", mockaso.Path("/users")).
Respond(
mockaso.WithJSON([]User{{ID: 1, Name: "Alice"}}),
mockaso.WithStatusCode(200),
)
client := server.Client()
resp, _ := client.Get("/users")
func MustStartNewServer ¶
func MustStartNewServer(opts ...ServerOption) *Server
MustStartNewServer creates a new mock server and starts it immediately. This is a convenience function equivalent to calling NewServer followed by MustStart. It panics if the server fails to start.
Example:
server := mockaso.MustStartNewServer(mockaso.WithLogger(t)) defer server.MustShutdown()
func NewServer ¶
func NewServer(opts ...ServerOption) *Server
NewServer creates a new mock server with the given options. The server is not started automatically - call Start or MustStart to begin accepting requests.
By default, the server uses a silent logger that produces no output. Use WithLogger, WithSlogLogger, or WithLogLogger to enable logging.
Example:
server := mockaso.NewServer(mockaso.WithLogger(t)) server.MustStart() defer server.MustShutdown()
func (*Server) Clear ¶
func (s *Server) Clear()
Clear removes all registered stubs from the server. The server continues running but will return 666 for all requests until new stubs are added. This method is thread-safe.
func (*Server) Client ¶
Client returns an HTTP client configured to work with this mock server. The returned client uses a custom transport that automatically resolves relative URLs (like "/api/users") to the server's base URL.
Example:
client := server.Client()
resp, err := client.Get("/api/users") // Automatically uses server.URL()
func (*Server) MustShutdown ¶
func (s *Server) MustShutdown()
MustShutdown stops the server and panics if an error occurs. This is a convenience method for tests, typically used with defer.
func (*Server) MustStart ¶
func (s *Server) MustStart()
MustStart starts the server and panics if an error occurs. This is a convenience method for tests where startup failure should be fatal.
func (*Server) Shutdown ¶
Shutdown stops the HTTP test server and cleans up resources. It is safe to call Shutdown on an already stopped server. Returns nil on success.
func (*Server) Start ¶
Start initializes and starts the HTTP test server. It is safe to call Start multiple times - subsequent calls are no-ops. Returns nil on success.
func (*Server) Stub ¶
func (s *Server) Stub(method string, url URLMatcher) Stub
Stub creates and registers a new stub for the given HTTP method and URL matcher. Stubs are evaluated in the order they are added - the first matching stub handles the request.
The method parameter should be an HTTP method like "GET", "POST", "PUT", etc. The url parameter is a URLMatcher that determines which requests this stub handles.
Example:
server.Stub("GET", mockaso.Path("/users")).
Match(mockaso.MatchHeader("Accept", "application/json")).
Respond(mockaso.WithJSON(users), mockaso.WithStatusCode(200))
func (*Server) TestServer ¶
TestServer returns the underlying httptest.Server. This is useful for advanced scenarios that require direct access to the test server.
type ServerOption ¶
type ServerOption func(*Server)
ServerOption is a function that configures a Server during initialization. Options are applied in the order they are provided to NewServer.
func WithLogLogger ¶
func WithLogLogger(logger *log.Logger) ServerOption
WithLogLogger sets a Logger from log.Logger.
Example:
logger := log.New(os.Stdout, "[MOCKASO] ", log.LstdFlags) server := mockaso.NewServer(mockaso.WithLogLogger(logger))
func WithLogger ¶
func WithLogger(logger Logger) ServerOption
WithLogger sets a Logger. Intended for use with testing.T.
Example:
func TestAPI(t *testing.T) {
server := mockaso.NewServer(mockaso.WithLogger(t))
// Server will log to test output
}
func WithSlogLogger ¶
func WithSlogLogger(logger *slog.Logger, level slog.Level) ServerOption
WithSlogLogger sets a Logger from slog.Logger. level is the slog.LogLevel that will be used.
Example:
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) server := mockaso.NewServer(mockaso.WithSlogLogger(logger, slog.LevelInfo))
type SlogLogger ¶
type SlogLogger struct {
// contains filtered or unexported fields
}
SlogLogger implementation of Logger using an slog.Logger. All log messages are emitted at the configured level.
Example:
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) server := mockaso.NewServer( mockaso.WithSlogLogger(logger, slog.LevelInfo), )
func NewSlogLogger ¶
func NewSlogLogger(logger *slog.Logger, level slog.Level) *SlogLogger
NewSlogLogger creates a new SlogLogger with the specified logger and level. All messages logged through this logger will use the given level.
func (*SlogLogger) Log ¶
func (l *SlogLogger) Log(args ...any)
func (*SlogLogger) Logf ¶
func (l *SlogLogger) Logf(format string, args ...any)
type Stub ¶
type Stub interface {
StubResponder
Match(...StubMatcherRule) StubResponder
}
Stub represents a configured HTTP endpoint mock with request matching rules and response configuration. It provides a fluent API for chaining matchers and response rules.
The typical usage pattern is:
- Create a stub with Server.Stub(method, urlMatcher)
- Optionally add matchers with Match(...)
- Configure the response with Respond(...)
Example:
server.Stub("POST", mockaso.Path("/users")).
Match(
mockaso.MatchHeader("Content-Type", "application/json"),
mockaso.MatchJSONBody(map[string]string{"name": "Alice"}),
).
Respond(
mockaso.WithStatusCode(201),
mockaso.WithJSON(map[string]any{"id": 123, "name": "Alice"}),
)
type StubMatcherRule ¶
type StubMatcherRule func() requestMatcherFunc
StubMatcherRule is a function that returns a request matcher. Multiple StubMatcherRules can be applied to a stub, and ALL must return true for the stub to match the request.
Matchers are evaluated after the URL and method match, in the order they were added to the stub.
Example:
server.Stub("GET", mockaso.Path("/users")).
Match(
mockaso.MatchHeader("Authorization", "Bearer token"),
mockaso.MatchQuery("active", "true"),
)
func MatchBodyMapFunc ¶
func MatchBodyMapFunc(bodyMatcher BodyMatcherMapFunc) StubMatcherRule
MatchBodyMapFunc sets a rule to match the http request with the given matcher based on the body as a map. The matcher is a func that receives the body parameters as a map. If the body is empty the map will be empty.
This is useful for partial matching or complex validation logic.
Example:
server.Stub("POST", mockaso.Path("/users")).
Match(mockaso.MatchBodyMapFunc(func(body map[string]any) bool {
name, ok := body["name"].(string)
return ok && len(name) > 0
}))
func MatchBodyStringFunc ¶
func MatchBodyStringFunc(bodyMatcher BodyMatcherStringFunc) StubMatcherRule
MatchBodyStringFunc sets a rule to match the http request with the given matcher based on the body as string. The matcher is a func that receives the body as plain text.
Example:
server.Stub("POST", mockaso.Path("/webhook")).
Match(mockaso.MatchBodyStringFunc(func(body string) bool {
return strings.Contains(body, "event=created")
}))
func MatchHeader ¶
func MatchHeader(key, value string) StubMatcherRule
MatchHeader sets a rule to match the http request with the given header value. The match is case-sensitive for the value, but header names follow HTTP canonicalization rules.
Example:
server.Stub("GET", mockaso.Path("/api")).
Match(mockaso.MatchHeader("Authorization", "Bearer secret-token"))
func MatchJSONBody ¶
func MatchJSONBody(body any) StubMatcherRule
MatchJSONBody sets a rule to match the http request with the given JSON body. The specified body will be marshaled and compared with the actual request body. JSON comparison is structural, so field order and whitespace are ignored.
Example:
expectedUser := User{Name: "Alice", Age: 30}
server.Stub("POST", mockaso.Path("/users")).
Match(mockaso.MatchJSONBody(expectedUser))
func MatchNoBody ¶
func MatchNoBody() StubMatcherRule
MatchNoBody sets a rule to match the http request with empty body.
Example:
server.Stub("GET", mockaso.Path("/ping")).
Match(mockaso.MatchNoBody())
func MatchParam ¶
func MatchParam(key, value string) StubMatcherRule
MatchParam sets a rule to match the http request with the given path param value. This requires that the URL was specified with URLPattern or PathPattern.
Example:
server.Stub("GET", mockaso.PathPattern("/users/{id}")).
Match(mockaso.MatchParam("id", "123"))
This matches: GET /users/123
func MatchQuery ¶
func MatchQuery(key, value string) StubMatcherRule
MatchQuery sets a rule to match the http request with the given query string value. Only the first value is checked if the query parameter appears multiple times.
Example:
server.Stub("GET", mockaso.Path("/users")).
Match(mockaso.MatchQuery("status", "active"))
This matches: GET /users?status=active
func MatchRawJSONBody ¶
func MatchRawJSONBody[T string | []byte | json.RawMessage](raw T) StubMatcherRule
MatchRawJSONBody sets a rule to match the http request with the given raw JSON body. The JSON is compared structurally, so formatting differences are ignored.
Example:
server.Stub("POST", mockaso.Path("/users")).
Match(mockaso.MatchRawJSONBody(`{"name":"Alice","age":30}`))
func MatchRequest ¶
func MatchRequest(requestMatcher RequestMatcherFunc) StubMatcherRule
MatchRequest sets a rule to match the http request given a custom matcher. This is the most flexible matching option and allows for arbitrary request validation.
Example:
server.Stub("GET", mockaso.Path("/api")).
Match(mockaso.MatchRequest(func(r *http.Request) bool {
return r.Header.Get("User-Agent") != ""
}))
type StubResponder ¶
type StubResponder interface {
Respond(...StubResponseRule)
}
StubResponder provides the final step in the fluent API for configuring a stub's response. After all matchers are defined, call Respond to set the HTTP response that will be returned when the stub matches.
Example:
stub.Respond(
mockaso.WithStatusCode(200),
mockaso.WithJSON(responseData),
mockaso.WithHeader("X-Custom", "value"),
)
type StubResponseRule ¶
type StubResponseRule func(*stubResponse)
StubResponseRule is a function that configures a stub's HTTP response. Multiple rules can be applied to a single response, and they are processed in the order they are provided to Respond.
Example:
stub.Respond(
mockaso.WithStatusCode(201),
mockaso.WithJSON(createdResource),
mockaso.WithHeader("Location", "/api/resources/123"),
)
func WithBody ¶
func WithBody(body any) StubResponseRule
WithBody sets the response body. Accepts []byte, string, json.RawMessage, or io.Reader. For other types, the value is converted using fmt.Sprintf("%v", value).
Example:
stub.Respond(mockaso.WithBody("Hello, World!"))
stub.Respond(mockaso.WithBody([]byte{0x89, 0x50, 0x4E, 0x47}))
func WithDelay ¶
func WithDelay(d time.Duration) StubResponseRule
WithDelay sets a delay time to the response. The delay is applied before writing the response body. If the request context is cancelled during the delay, the response is aborted.
Example:
stub.Respond( mockaso.WithJSON(data), mockaso.WithDelay(500 * time.Millisecond), // Simulate slow API )
func WithHeader ¶
func WithHeader(key, value string) StubResponseRule
WithHeader sets a response header. If the key already exists it will be overwritten.
Example:
stub.Respond(
mockaso.WithHeader("Content-Type", "text/plain"),
mockaso.WithHeader("X-Request-ID", "abc-123"),
)
func WithHeaders ¶
func WithHeaders(headers map[string]string) StubResponseRule
WithHeaders sets a set of response headers. These headers will be added to the already specified headers. If any key already exists it will be overwritten.
Example:
headers := map[string]string{
"X-RateLimit-Limit": "100",
"X-RateLimit-Remaining": "99",
}
stub.Respond(mockaso.WithHeaders(headers))
func WithJSON ¶
func WithJSON(body any) StubResponseRule
WithJSON sets the response content with the marshal output of the given body. The response will include the Content-Type:application/json header. Panics if the body cannot be marshaled to JSON.
Example:
user := User{ID: 1, Name: "Alice"}
stub.Respond(mockaso.WithJSON(user))
// Or with inline data
stub.Respond(mockaso.WithJSON(map[string]any{
"users": []string{"Alice", "Bob"},
"total": 2,
}))
func WithRawJSON ¶
func WithRawJSON[T string | []byte | json.RawMessage](raw T) StubResponseRule
WithRawJSON sets the response content with the given JSON. The response will include the Content-Type:application/json header. The provided JSON is validated before being set.
Example:
stub.Respond(mockaso.WithRawJSON(`{"status":"ok","count":42}`))
func WithStatusCode ¶
func WithStatusCode(statusCode int) StubResponseRule
WithStatusCode sets the response status code. If not specified, the default status code is 200 (OK).
Example:
stub.Respond(mockaso.WithStatusCode(404))
type URLMatcher ¶
URLMatcher is a function that matches against a request URL. It is the primary matching mechanism for stubs and is evaluated before any StubMatcherRule functions.
URLMatchers can extract parameters from URL patterns and store them in the stub for later use with MatchParam.
func Path ¶
func Path(path string) URLMatcher
Path will match http request when the value specified is equals to the request URL path part.
Example:
server.Stub("GET", mockaso.Path("/api/users"))
func PathPattern ¶
func PathPattern(pattern string) URLMatcher
PathPattern will match http request when the given URL pattern match to the request URL path part. Can specify path params with {param_name} notation and then use it in matcher. Can't use parameters in query string, only path will be evaluated.
Example:
PathPattern("/api/users/{user_id}")
func PathRegex ¶
func PathRegex(pattern string) URLMatcher
PathRegex will match http request when the regex pattern specified match to the request URL path part.
Example:
server.Stub("GET", mockaso.PathRegex(`^/users/\d+$`))
func URL ¶
func URL(u string) URLMatcher
URL will match http request when the value specified is equals to the full request URL.
Example:
server.Stub("GET", mockaso.URL("http://example.com/api/users"))
func URLPattern ¶
func URLPattern(pattern string) URLMatcher
URLPattern will match http request when the given URL pattern match to the request URL. Can specify path params with {param_name} notation and then use it in matcher. Can use parameters in query string.
Example:
URLPattern("/api/users/{user_id}")
URLPattern("/api/users/{user_id}?attrs={attrs}")
func URLRegex ¶
func URLRegex(pattern string) URLMatcher
URLRegex will match http request when the regex pattern specified match to the request URL.
Example:
server.Stub("GET", mockaso.URLRegex(`^http://example\.com/users/\d+$`))