Mocker — Multi-Server Routing¶
TL;DR — One mocker binary, multiple logical servers on different ports; each server owns its stubs and exposes a deterministic channel name so multiple runners can target specific servers without cross-talk.
When to use¶
- Your system-under-test calls several downstream services that you want to mock independently in one process.
- You want each mock to have its own response shape, latency, and failure mode without spinning up three containers.
- You need a worked example of the
Servers(plural) YAML root and the channel-name convention.
YAML configuration¶
DataSources:
- Name: OrderResponses
Generator: FromFileSystem
GeneratorConfiguration:
DataArrangeOrder: AsciiAsc
FileSystem: { Path: Fixtures/orders }
- Name: PaymentResponses
Generator: FromFileSystem
GeneratorConfiguration:
DataArrangeOrder: AsciiAsc
FileSystem: { Path: Fixtures/payments }
- Name: CatalogResponses
Generator: FromFileSystem
GeneratorConfiguration:
DataArrangeOrder: AsciiAsc
FileSystem: { Path: Fixtures/catalog }
Stubs:
- Name: OrdersStub
Processor: DataSourceResponse
DataSourceNames: [OrderResponses]
ProcessorConfiguration: { StatusCode: 200 }
- Name: PaymentsStub
Processor: DataSourceResponse
DataSourceNames: [PaymentResponses]
ProcessorConfiguration: { StatusCode: 200 }
- Name: CatalogStub
Processor: DataSourceResponse
DataSourceNames: [CatalogResponses]
ProcessorConfiguration: { StatusCode: 200 }
Servers:
- Name: orders
InstanceName: primary
Http:
Port: 8081
IsLocalhost: false
Endpoints:
- Path: /orders/{id}
Actions:
- { Name: GetOrder, Method: Get, TransactionStubName: OrdersStub }
- Path: /orders
Actions:
- { Name: CreateOrder, Method: Post, TransactionStubName: OrdersStub }
- Name: payments
InstanceName: primary
Http:
Port: 8082
IsLocalhost: false
Endpoints:
- Path: /payments
Actions:
- { Name: Charge, Method: Post, TransactionStubName: PaymentsStub }
- Name: catalog
InstanceName: primary
Http:
Port: 8083
IsLocalhost: false
Endpoints:
- Path: /catalog/{sku}
Actions:
- { Name: GetItem, Method: Get, TransactionStubName: CatalogStub }
C# (CAC) usage¶
No custom processor is required for pure routing. The mocker is fully YAML-driven once Bootstrap runs:
QaaS.Mocker.Bootstrap.New(args).Run();
Add custom processors per stub when you need behaviour beyond DataSourceResponse — see Processors — custom authoring guide.
Minimal example¶
A single server with one endpoint, copied from one fixture file:
DataSources:
- Name: OrderResponses
Generator: FromFileSystem
GeneratorConfiguration:
DataArrangeOrder: AsciiAsc
FileSystem: { Path: Fixtures/orders }
Stubs:
- Name: OrdersStub
Processor: DataSourceResponse
DataSourceNames: [OrderResponses]
ProcessorConfiguration: { StatusCode: 200 }
Servers:
- Name: orders
InstanceName: primary
Http:
Port: 8081
IsLocalhost: false
Endpoints:
- Path: /orders
Actions:
- { Name: CreateOrder, Method: Post, TransactionStubName: OrdersStub }
Realistic example¶
Two instances of the same logical server (blue/green) on different ports, so runners can deliberately split traffic to test cutovers:
Servers:
- Name: orders
InstanceName: blue
Http: { Port: 8081, IsLocalhost: false, Endpoints: [ ] } # blue stubs here
- Name: orders
InstanceName: green
Http: { Port: 8181, IsLocalhost: false, Endpoints: [ ] } # green stubs here
Runner A points at http://localhost:8081 (instance blue); Runner B points at :8181 (instance green). Both can run in parallel against the same mocker process without cross-contamination.
Edge cases¶
Server:(singular) andServers:(plural) are mutually exclusive. Use plural the moment you need more than one.- Ports must be unique across
Servers[*].Http.Port; the mocker fails fast at startup if not. Nameis required when there is more than one server; the runner uses it to disambiguate channels.InstanceNamedefaults to a deterministic value when omitted, but pinning it explicitly makes channel names predictable in CI logs.IsLocalhost: falsebinds to0.0.0.0(reachable from sibling containers). Settruefor laptop dev to stay on127.0.0.1.