WireMock Runner Hosting¶
This guide provides step-by-step instructions for configuring WireMock Runner hosting in your Aspire AppHost. WireMock Runner orchestrates multiple WireMock mock services as a single managed resource, allowing you to pull mock definitions from WireMock Cloud using API tokens.
Experimental Feature
WireMock Runner APIs are marked as experimental (SAIFMOCK001). See SAIFMOCK001 diagnostic for suppression options.
📚 Useful Resources¶
📋 Prerequisites¶
Before you begin, ensure you have:
- ✅ .NET 10.0 SDK installed
- ✅ Docker Desktop running
- ✅ Node.js and npm installed (required for the provision-and-pull phase; used to install the WireMock CLI automatically)
- ✅ An API project with 1 or more external API dependencies you wish to mock
- ✅ WireMock Cloud account and API token
- ✅ WireMock Cloud project(s) with mocks defined (or use auto-provisioning)
📁 Projects¶
- AppHost Project: Contains logic for setting up your application and dependencies
🛠️ WireMock Runner - Aspire Hosting Extensions¶
Overview¶
The WireMock Runner namespace (SAIF.Platform.Aspire.Hosting.WiremockRunner) provides Aspire hosting extensions for orchestrating multiple WireMock mock services as a single managed resource. This enables you to:
- Manage multiple mock services through a single runner resource
- Pull mock definitions from WireMock Cloud using API tokens
- Auto-provision new mock APIs in WireMock Cloud with seed stubs
- Integrate with Aspire's service discovery
- Organize mock configurations in a dedicated directory
- Iterate on mock stubs without restarting the entire AppHost
For a detailed comparison with WireMock CLI and other approaches, see Comparison with Other Mocking Approaches.
🚀 Step-by-Step Implementation¶
Step 1: Add Package Reference¶
Add a reference to the SAIF.Platform.Aspire.Hosting NuGet package in your AppHost project:
Step 2: Suppress Experimental Warning¶
Since WireMock Runner is experimental, you'll need to suppress the SAIFMOCK001 warning. See SAIFMOCK001 diagnostic documentation for suppression options.
Step 3: Add WireMock Runner Resource¶
Create the WireMock Runner resource. The API token is automatically configured:
API Token Handling:
- Local Development: Prompts for token as a secret parameter in the Aspire dashboard
- CI/CD (when
CI=trueenv var is set): UsesWMC_API_TOKENenvironment variable directly (no parameter prompt)
To obtain your WireMock Cloud API token:
- Log in to WireMock Cloud
- Navigate to Settings → API Tokens
- Create a new API token or copy an existing one
CI/CD Configuration:
Set the WMC_API_TOKEN environment variable in your CI/CD pipeline using integrationTestEnvironmentVariables:
extends:
template: azure-dotnet-api-pr-v3.yml@templates
parameters:
# ... other parameters ...
integrationTestEnvironmentVariables:
- name: WMC_API_TOKEN
value: $(WmcApiToken) # From variable group/secret
See Integration Test Environment Variables for full parameter documentation.
Step 4: Add Mock Services¶
Add individual mock services to the runner. Each mock service can either reference an existing WireMock Cloud project or be provisioned automatically:
// Reference an existing WireMock Cloud project (using project ID)
var externalApi = wiremockRunner.AddMock(
name: "external-api",
port: 8080,
wiremockProjectId: "abc123xyz"
);
// Add mock service that will be created in WireMock Cloud (no project ID)
// The provision resource will create the mock API and set organization-wide access
var newApi = wiremockRunner.AddMock(
name: "new-api",
port: 8082
);
Finding Your WireMock Project ID (for existing mocks):
- Navigate to your mock in WireMock Cloud
- Copy the URL from your browser:
https://app.wiremock.cloud/mock-apis/abc123xyz/stubs/... - The
wiremockProjectIdis the unique identifier in the URL (e.g.,abc123xyz)
Step 5: Add Seed Stubs (Optional)¶
For auto-provisioned mocks, provide initial stub data so the mock is immediately useful:
var newApi = wiremockRunner.AddMock("new-api", 8082)
.WithSeeds(Path.Combine(builder.AppHostDirectory, "seeds", "new-api"));
Create a stubs.json file in the seed directory using the WireMock export format:
{
"mappings": [
{
"id": "a1b2c3d4-0001-4000-8000-000000000001",
"name": "List Animals",
"request": { "method": "GET", "url": "/animals" },
"response": {
"status": 200,
"jsonBody": [
{ "name": "dog", "type": "domestic" },
{ "name": "cat", "type": "domestic" }
]
}
}
]
}
Stable Stub IDs
Include a stable id (UUID) for each mapping. This makes imports idempotent — re-running provision-and-pull updates existing stubs rather than creating duplicates.
Step 6: Reference Mocks in Your Application¶
Wire your application to reference the mock services:
builder
.AddProject<Projects.MyApiService>("my-api-service")
.WithReference(externalApi)
.WithReference(newApi)
.WaitFor(externalApi)
.WaitFor(newApi);
📝 Complete Example¶
Here's a complete AppHost configuration using WireMock Runner:
using SAIF.Platform.Aspire.Hosting.WiremockRunner;
var builder = DistributedApplication.CreateBuilder(args);
// Create WireMock Runner resource
// - Local dev: prompts for token in Aspire dashboard
// - CI/CD (CI=true): reads from WMC_API_TOKEN environment variable
var wiremockRunner = builder.AddWiremockRunner("wiremock");
// Reference existing WireMock Cloud projects
var customerApi = wiremockRunner.AddMock("customer-api", 8080, "abc123xyz");
var paymentApi = wiremockRunner.AddMock("payment-api", 8081, "def456uvw");
// Auto-provision a new mock with seed stubs
var inventoryApi = wiremockRunner.AddMock("inventory-api", 8082)
.WithSeeds(Path.Combine(builder.AppHostDirectory, "seeds", "inventory-api"));
// Wire application to mock services
builder
.AddProject<Projects.MyApiService>("my-api-service")
.WithReference(customerApi)
.WithReference(paymentApi)
.WithReference(inventoryApi)
.WaitFor(customerApi)
.WaitFor(paymentApi)
.WaitFor(inventoryApi);
builder.Build().Run();
🔍 How It Works¶
Architecture¶
┌─────────────────────────────────────────────────────────┐
│ WireMock Runner │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ wiremock-provision-and-pull (runs on start) │ │
│ │ │ │
│ │ Phase 1: Provision │ │
│ │ - Creates mock APIs in WireMock Cloud │ │
│ │ - Grants org-wide ACL (mock_api_editor) │ │
│ │ - Saves project IDs to .provisioned.json │ │
│ │ │ │
│ │ Phase 1.5: Import Seeds │ │
│ │ - Uploads stubs.json to WireMock Cloud │ │
│ │ - Uses wiremock import CLI command │ │
│ │ │ │
│ │ Phase 2: Pull │ │
│ │ - Downloads all mock stubs from WireMock Cloud │ │
│ │ - Saves to .wiremock/ directory as YAML │ │
│ │ │ │
│ │ Phase 2.5: Fix Ports │ │
│ │ - Corrects ports in wiremock.yaml to match config │ │
│ └────────────────────┬───────────────────────────────┘ │
│ starts after completion │
│ ▼ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ wiremock-runner (container) │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Mock Service │ │ Mock Service │ ... │ │
│ │ │ Port: 8080 │ │ Port: 8082 │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Your Application Service │
│ - References mock services via WithReference() │
│ - Uses Aspire service discovery │
└─────────────────────────────────────────────────────────┘
Startup Flow¶
When the AppHost starts:
- Provision-and-Pull runs automatically:
- Phase 1: Creates any auto-provisioned mock APIs in WireMock Cloud (idempotent — skips if already created)
- Phase 1.5: Imports seed stubs from
WithSeeds()directories into WireMock Cloud - Phase 2: Pulls all mock stubs from WireMock Cloud to the
.wiremock/directory - Phase 2.5: Fixes ports in
wiremock.yamlto match the configured mock ports - Runner Container starts after provision-and-pull completes, serving stubs from the
.wiremock/bind mount - Mock resources become
Runningin the Aspire dashboard with allocated endpoints - Your application starts after mocks are ready (via
WaitFor())
Inner Loop: Editing Stubs¶
To iterate on mock stubs without restarting the entire AppHost:
- Edit the
stubs.jsonfile in your seed directory - Re-run the
wiremock-provision-and-pullresource from the Aspire dashboard (click Start) - Runner auto-restarts — the runner container is automatically restarted via
docker restartafter provision-and-pull completes on subsequent runs - Verify restart — check the logs of
wiremock-runnerin the Aspire dashboard for startup messages matching your re-run timestamp
Confirming the restart
The runner resource stays in the Running state throughout the container restart, so dashboard status alone doesn't indicate completion. Check the wiremock-runner logs for the WireMock startup banner to confirm new stubs are loaded.
Why docker restart?
WireMock Runner loads stubs at container startup from the bind-mounted .wiremock/ directory. Updating files on disk alone does not trigger an in-memory reload. The WireMock admin API reset endpoints (POST /__admin/mappings/reset) only reset to the startup state, not the current disk state. A container restart is the only reliable way to pick up changes.
Directory Structure¶
The WireMock Runner organizes mock files in a structured directory:
.wiremock/
├── .manifest.json # Mock metadata (generated)
├── .provisioned.json # Provisioned project IDs (generated)
├── wiremock.yaml # WireMock Runner configuration (generated)
├── customer-api/
│ ├── mappings/
│ │ └── stub-mappings.yaml
│ └── __files/
├── inventory-api/
│ ├── mappings/
│ │ └── stub-mappings.yaml
│ └── __files/
└── payment-api/
├── mappings/
│ └── stub-mappings.yaml
└── __files/
Seed Directory Structure¶
Seed stubs are stored alongside the AppHost project:
AppHost/
├── AppHost.cs
├── seeds/
│ └── inventory-api/
│ └── stubs.json # WireMock export format
└── .wiremock/ # Generated by provision-and-pull
🎯 Usage Scenarios¶
Scenario 1: Multi-Service Development¶
When developing a service that depends on multiple external APIs:
var wiremockRunner = builder.AddWiremockRunner("wiremock");
// Mock all external dependencies
var customerApi = wiremockRunner.AddMock("customer-api", 8080, "proj1");
var inventoryApi = wiremockRunner.AddMock("inventory-api", 8081, "proj2");
var shippingApi = wiremockRunner.AddMock("shipping-api", 8082, "proj3");
// Your order service references all mocks
builder.AddProject<Projects.OrderService>("order-service")
.WithReference(customerApi)
.WithReference(inventoryApi)
.WithReference(shippingApi);
Scenario 2: Rapid Prototyping with Seeds¶
Start a new mock from scratch with seed data:
var notificationApi = wiremockRunner.AddMock("notification-api", 8083)
.WithSeeds(Path.Combine(builder.AppHostDirectory, "seeds", "notification-api"));
{
"mappings": [
{
"id": "b2c3d4e5-0001-4000-8000-000000000001",
"name": "Send Notification",
"request": { "method": "POST", "url": "/notifications" },
"response": { "status": 202, "jsonBody": { "status": "queued" } }
}
]
}
Edit the stubs, re-run provision-and-pull from the dashboard, and see changes immediately.
Scenario 3: Team Collaboration¶
Share mock definitions across the team using WireMock Cloud:
- Developer A creates/updates mocks in WireMock Cloud (or edits seed stubs and re-runs provision-and-pull)
- Developer B pulls latest mocks by restarting the AppHost
- CI/CD uses the same WireMock Cloud projects for integration tests
🔧 Configuration Options¶
AddWiremockRunner()¶
Creates the WireMock Runner resource with automatic API token handling. See Step 3 for token configuration details.
WithDirectory() (Optional)¶
Specifies the local directory for storing mock configurations (default: ./.wiremock):
var wiremockRunner = builder.AddWiremockRunner("wiremock")
.WithDirectory("./mocks"); // Custom directory (optional)
AddMock()¶
Adds a mock service to the runner. Two modes are supported:
Reference an existing WireMock Cloud project:
var mock = wiremockRunner.AddMock(
name: "service-name", // Service discovery name
port: 8080, // Container target port
wiremockProjectId: "abc123xyz" // WireMock Cloud project ID
);
Provision a new mock API in WireMock Cloud:
var mock = wiremockRunner.AddMock(
name: "service-name", // Service discovery name + WireMock Cloud mock name
port: 8080 // Container target port
);
When wiremockProjectId is omitted, the provision-and-pull resource will:
- Create the mock API in WireMock Cloud via the REST API (
POST /v1/mock-apis) - Grant organization-wide access with
mock_api_editorrole - Save the created project ID to
.wiremock/.provisioned.json - Import any seed stubs, then pull all stubs to disk
Provisioned project IDs persist in .provisioned.json so mock APIs are only created once.
WithSeeds()¶
Specifies a directory containing a stubs.json file for initial stub data. Only applies to auto-provisioned mocks (those without a wiremockProjectId). See Step 5 for format details and best practices.
var mock = wiremockRunner.AddMock("my-service", 8082)
.WithSeeds(Path.Combine(builder.AppHostDirectory, "seeds", "my-service"));
🐛 Troubleshooting¶
Issue: Mocks Not Loading¶
Symptoms: Mock services start but don't respond to requests
Solutions:
- Verify the WireMock project ID is correct
- Check that the API token has access to the project
- Inspect the
.wiremockdirectory to ensure files were downloaded - Check the Aspire dashboard for runner errors
Issue: Authentication Failed¶
Symptoms: Error messages about invalid API token
Solutions:
- Local Development: Enter the correct token when prompted in the Aspire dashboard
- CI/CD: Verify the
WMC_API_TOKENenvironment variable is set correctly - Ensure the token hasn't expired in WireMock Cloud
Issue: Port Conflicts¶
Symptoms: Mock services fail to start due to port in use
Solutions:
- Ensure each mock uses a unique port
- Check for other processes using the same ports
- Use higher port numbers (e.g., 8080+) to avoid conflicts
Issue: Service Discovery Not Working¶
Symptoms: Application can't resolve mock service endpoints
Solutions:
- Ensure you're using
.WithReference(mockResource)in your application - Verify the mock name matches what you're requesting
- Check the Aspire dashboard to confirm service registration
Issue: Stub Changes Not Reflected¶
Symptoms: Edited stubs.json but mock still returns old data
Solutions:
- Verify the file was saved
- Re-run the
wiremock-provision-and-pullresource from the Aspire dashboard — the runner container restarts automatically - If auto-restart fails, manually restart the
wiremock-runnercontainer from the dashboard
Note
WireMock Runner only reads stubs at container startup. Editing files on disk requires a container restart to take effect.
📊 Comparison with Other Mocking Approaches¶
| Approach | WireMock Runner | WireMock CLI | Container-based |
|---|---|---|---|
| Runtime | Container (Docker) | Executable | Container |
| CI/Integration Tests | ✅ Supported | ❌ Not supported | ✅ Supported |
| Setup Complexity | Medium | Low | Low |
| Authentication | API token (automatic) | Optional | Not applicable |
| Orchestration | Centralized | Per-mock | Per-container |
| Seed Stubs | ✅ WithSeeds() | ❌ N/A | ⚠️ Manual setup |
| Team Sharing | ✅ Via WireMock Cloud | ✅ Via WireMock Cloud | ⚠️ Manual file sharing |
| Multi-Mock | ✅ Single resource | ⚠️ Multiple resources | ⚠️ Multiple containers |
| Production Ready | ⚠️ Experimental | ✅ Stable | ✅ Stable |
🎓 Best Practices¶
Organize Mock Projects by Domain¶
Create separate WireMock Cloud projects for different domains:
customer-service-mockspayment-service-mocksinventory-service-mocks
Use Descriptive Mock Names¶
Choose names that clearly indicate what's being mocked:
var customerApiMock = wiremockRunner.AddMock("customer-api", 8080, "proj1");
// Not: var mock1 = wiremockRunner.AddMock("mock1", 8080, "proj1");
Document Project IDs¶
Document which WireMock Cloud project ID corresponds to which service:
// WireMock Cloud Project IDs:
// - abc123xyz: Customer API (https://app.wiremock.cloud/mock-apis/abc123xyz)
// - def456uvw: Payment API (https://app.wiremock.cloud/mock-apis/def456uvw)
var customerApi = wiremockRunner.AddMock("customer-api", 8080, "abc123xyz");
var paymentApi = wiremockRunner.AddMock("payment-api", 8081, "def456uvw");
When to Use WireMock Runner vs. CLI¶
Use WireMock Runner when you need integration tests in CI/CD, container-based orchestration, centralized multi-mock management, or seed stubs for rapid prototyping.
Use WireMock CLI when you need a stable solution for local-only development with simple, independent mock scenarios and minimal setup.
🔗 Related Resources¶
💬 Feedback¶
WireMock Runner is an experimental feature. Please provide feedback through:
- 🐛 Issues for bugs or problems
- 💡 Feature requests for improvements
- 📝 Discussions for general feedback
Visit the Forge repository to share your thoughts.