Mock server¶
See the Mock server guide and Proxy testing guide for usage.
Services¶
asyncly.srvmocker.service.start_service
async
¶
start_service(
routes: Iterable[MockRoute],
*,
ssl_context: SSLContext | None = None,
) -> AsyncGenerator[MockService, None]
Start a real aiohttp.TestServer for the given routes.
An async context manager. On enter it binds the server to a free port and
yields a MockService whose url points
at it; on exit it shuts the server down.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
routes
|
Iterable[MockRoute]
|
The routes to serve. Several routes may share a
|
required |
ssl_context
|
SSLContext | None
|
If given, serve over HTTPS; |
None
|
Yields:
| Name | Type | Description |
|---|---|---|
MockService |
AsyncGenerator[MockService, None]
|
Handle to register responses and assert on requests. |
Example
Source code in asyncly/srvmocker/service.py
asyncly.srvmocker.proxy.start_proxy
async
¶
start_proxy(
*, auth: BasicAuth | None = None
) -> AsyncGenerator[MockProxyService, None]
Start an in-process forwarding HTTP proxy for tests.
An async context manager. It records every request that passes through and
forwards it to the absolute target the client requested (typically another
start_service), relaying the response
verbatim. Only plain HTTP targets are supported (no CONNECT tunnelling).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
auth
|
BasicAuth | None
|
If given, require a matching |
None
|
Yields:
| Name | Type | Description |
|---|---|---|
MockProxyService |
AsyncGenerator[MockProxyService, None]
|
Handle exposing the proxy |
Source code in asyncly/srvmocker/proxy.py
asyncly.srvmocker.models.MockService
dataclass
¶
MockService(
history: MutableSequence[RequestHistory],
history_map: MutableMapping[
str, MutableSequence[RequestHistory]
],
url: URL,
handlers: MutableMapping[str, BaseMockResponse],
_handler_names: frozenset[str] = frozenset(),
)
Handle to a running mock server.
Returned by start_service. Use it to
register responses, read the recorded request history, and assert on what a
client sent. The url attribute is the base URL to point a client at.
register
¶
register(name: str, resp: BaseMockResponse) -> None
Register (or replace) the response returned for a handler name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
A |
required |
resp
|
BaseMockResponse
|
The response to return. May be re-registered mid-test to change behavior. |
required |
Source code in asyncly/srvmocker/models.py
get_calls
¶
get_calls(name: str) -> list[RequestHistory]
last_call
¶
last_call(name: str) -> RequestHistory
Return the most recent call for a handler.
Raises:
| Type | Description |
|---|---|
AssertionError
|
If the handler recorded no calls. |
Source code in asyncly/srvmocker/models.py
assert_called
¶
assert_called(
name: str,
*,
times: int | None = None,
json: object = None,
body: bytes | None = None,
headers: dict[str, str] | None = None,
query: dict[str, str] | None = None,
) -> None
Assert that a matching request was received.
With only times, asserts the exact call count. With predicates,
asserts at least one recorded call matched all of them: json and
body match exactly, while headers and query match as a
subset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The handler name to check. |
required |
times
|
int | None
|
If given, the exact number of calls expected. |
None
|
json
|
object
|
Expected parsed JSON body (exact match). |
None
|
body
|
bytes | None
|
Expected raw body bytes (exact match). |
None
|
headers
|
dict[str, str] | None
|
Header key/values that must all be present. |
None
|
query
|
dict[str, str] | None
|
Query key/values that must all be present. |
None
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If no recorded call satisfies the criteria. |
Source code in asyncly/srvmocker/models.py
assert_not_called
¶
Assert the handler received no requests.
Raises:
| Type | Description |
|---|---|
AssertionError
|
If any call was recorded for |
Source code in asyncly/srvmocker/models.py
asyncly.srvmocker.proxy.MockProxyService
dataclass
¶
MockProxyService(
url: URL, history: list[RequestHistory] = list()
)
Handle to a running mock forwarding proxy.
Returned by start_proxy. Point a client at
it via proxy=proxy.url and assert on the requests that passed through.
The history holds every request the proxy received.
assert_called
¶
assert_called(
*,
times: int | None = None,
target: URL | str | None = None,
method: str | None = None,
json: object = None,
body: bytes | None = None,
headers: dict[str, str] | None = None,
query: dict[str, str] | None = None,
) -> None
Assert that a matching request passed through the proxy.
Like MockService.assert_called, plus two proxy-specific predicates:
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
times
|
int | None
|
If given, the exact number of forwarded requests expected. |
None
|
target
|
URL | str | None
|
Expected absolute destination URL the client asked for. |
None
|
method
|
str | None
|
Expected HTTP method. |
None
|
json
|
object
|
Expected parsed JSON body (exact match). |
None
|
body
|
bytes | None
|
Expected raw body bytes (exact match). |
None
|
headers
|
dict[str, str] | None
|
Header key/values that must all be present (e.g.
|
None
|
query
|
dict[str, str] | None
|
Query key/values that must all be present. |
None
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If no recorded request satisfies the criteria. |
Source code in asyncly/srvmocker/proxy.py
Routes & history¶
asyncly.srvmocker.models.MockRoute
dataclass
¶
MockRoute(
method: str,
path: str,
handler_name: str,
match: Match | None = None,
)
Binds an HTTP method and path to a named handler.
Attributes:
| Name | Type | Description |
|---|---|---|
method |
str
|
HTTP method, e.g. |
path |
str
|
URL path, e.g. |
handler_name |
str
|
Label a response is registered under via
|
match |
Match | None
|
Optional |
asyncly.srvmocker.models.RequestHistory
dataclass
¶
A single recorded request.
Attributes:
| Name | Type | Description |
|---|---|---|
request |
BaseRequest
|
The aiohttp request object (headers, query, url, method). |
body |
bytes
|
The raw request body bytes. |
Matching¶
asyncly.srvmocker.matching.Match
dataclass
¶
Match(
json: Any = None,
body: bytes | None = None,
headers: dict[str, str] | None = None,
query: dict[str, str] | None = None,
)
Request matcher attached to a MockRoute.
json: parsed JSON body must equal this value exactly. body: raw body bytes must equal this value exactly. headers: every (key, value) here must be present in request headers (subset). query: every (key, value) here must be present in request query (subset).
Match is value-immutable: headers and query dicts are defensively
copied at construction so caller-side mutation cannot affect matcher
behavior. The instances themselves remain unhashable due to dict
fields -- wrap in a tuple of items if you need hashability.
Exceptions¶
asyncly.srvmocker.exceptions.SrvMockerError
¶
Bases: Exception
Base exception for srvmocker.
asyncly.srvmocker.exceptions.SequenceExhausted
¶
Bases: SrvMockerError
Raised by SequenceResponse when responses run out and on_exhausted='raise'.
asyncly.srvmocker.exceptions.UnknownHandlerError
¶
Bases: SrvMockerError
Raised when register() is called with a name not declared in any MockRoute.