Engineering note
Testing at application boundaries
Verification across processing, HTTP, socket and packaging boundaries.
APIs / Verification
Test scope
Direct controller tests exclude route selection, middleware, request binding and upstream dispatch. Those behaviours require tests through the application pipeline.
Processing decisions can be inspected using fake connections. Protocol behaviour such as TCP framing requires real socket traffic. Test scope should follow the behaviour under verification.
| Boundary | Keep real | Control or replace | What remains unchecked |
|---|---|---|---|
| Rule or processing test | The rule, transformation or routing decision. | Connections and external services; inspect exact output. | Transport framing, HTTP wiring and packaging. |
| Application HTTP pipeline | Routing, middleware, dependency wiring and response serialisation. | Upstreams using a loopback simulator. | Deployed process permissions and container networking. |
| Protocol socket test | Transport adapters and real TCP, TLS, UDP or TFTP traffic. | Local peers, temporary identities and test configuration. | Physical diode behaviour and the deployed network. |
| Packaged application | Built process, listener and deployment configuration. | Controlled external dependencies. | The full operational environment and vendor availability. |
Upstream request assertions
The API integration tests verify that caller-supplied authorisation headers are replaced with server-managed values at the upstream boundary. A successful HTTP response alone would not detect incorrect credential forwarding.
Additional cases inspect forwarded paths, query parameters, cursors, upstream errors and cancellation. Controlled upstreams keep these checks independent of vendor availability and live credentials.
ASP.NET Core WebApplicationFactory provides an in-process HTTP test host. Individual tests may still use real sockets for simulated upstreams or protocol peers.
Credential-forwarding example
- Arrange: start a controlled loopback upstream and point the real application route at it. Configure a fictional server-managed key and send a different, fictional caller-supplied value.
- Act: call the public route through the application test host, including its middleware and proxy transforms.
- Assert: inspect the upstream request. It must carry the configured server value and not the caller's value; the expected path and query must also reach the upstream.
This example uses synthetic values to illustrate the documented header-replacement tests. The upstream request is the decisive assertion: a permissive fake service could return success despite receiving the wrong credential.
A companion regression case can simulate token-acquisition failure and assert a local Problem Details response without upstream dispatch. Upstream rejection requires a separate case because its response contract is preserved by the passthrough.
Protocol and packaging tests
The networking suites use fake connections for sanitisation, channel selection and held-release assertions. Protocol tests cover protobuf length prefixes, continuous XML over TLS, inverted connection roles and EOF completion.
Fixture substitutions define the limits of each result. A test signer excludes production cryptography; a container health check covers reachability rather than a complete permissions assessment.
Test isolation and execution
- Give connections distinct identifiers and ports, then close and delete them during cleanup.
- Poll for the expected state with a deadline rather than waiting a fixed interval and hoping it is ready.
- Use controlled upstream success, rejection, delay and cancellation scenarios.
- Keep shared logging and filesystem state isolated or restore it after the test.
- Check that tests were discovered and executed. A green process with no tests run provides no regression evidence.
Simulated contracts require maintenance as upstream behaviour changes. Separate interoperability checks are needed for behaviours the fixtures cannot establish.
Related notes: framing messages on a byte stream and making dependency boundaries explicit.
Examples are generalised or synthetic and omit operational details and identifying information.
← All engineering notes