Aspire extension that enables hosting Microcks as a service, managing mocks for dependencies and contract-testing of your API endpoints in your .NET App.
GitHub Workflow Status Version License Project Chat Artifact HUB CNCF Landscape
Current development version is 0.1.0.
Code Smells Reliability Rating Bugs Coverage Technical Debt Security Rating Maintainability Rating
FOSSA Status FOSSA Status FOSSA Status
CII Best Practices OpenSSF Scorecard
- Documentation
- Microcks Community and community meeting
- Join us on Discord, on GitHub Discussions or CNCF Slack #microcks channel
To get involved with our community, please make sure you are familiar with the project's Code of Conduct.
dotnet add package Microcks.Aspire --version 0.1.0
With Aspire, you add Microcks as a resource to your distributed application. This library requires a Microcks uber distribution (with no MongoDB dependency).
In your AppHost Program.cs:
var microcks = builder.AddMicrocks("microcks") .WithImage("microcks/microcks-uber", "latest");
To use Microcks mocks or contract-testing features, you first need to import OpenAPI, Postman Collection, GraphQL or gRPC artifacts. Artifacts can be imported as main/Primary ones or as secondary ones. See Multi-artifacts support for details.
With Aspire, you import artifacts directly when adding the Microcks resource to your distributed application:
var microcks = builder.AddMicrocks("microcks") .WithMainArtifacts( "resources/third-parties/apipastries-openapi.yaml", "resources/order-service-openapi.yaml" ) .WithSecondaryArtifacts( "resources/order-service-postman-collection.json", "resources/third-parties/apipastries-postman-collection.json" );
You can also import full repository snapshots at once:
var microcks = builder.AddMicrocks("microcks") .WithSnapshots("microcks-repository.json");
During your test setup, you'd probably need to retrieve mock endpoints provided by Microcks to setup your base API url calls. With Aspire, you can do it like this:
// From the MicrocksResource directly var pastryApiUrl = microcksResource .GetRestMockEndpoint("API Pastries", "0.0.1") .ToString();
The MicrocksResource provides methods for different supported API styles/protocols (Soap, GraphQL, gRPC,...).
You can then use these endpoints to configure your HTTP clients in tests:
var webApplicationFactory = new WebApplicationFactory<Program>() .WithWebHostBuilder(builder => { builder.UseEnvironment("Test"); builder.UseSetting("PastryApi:BaseUrl", pastryApiUrl); });
Once the mock endpoint has been invoked, you'd probably need to ensure that the mock have been really invoked.
With Aspire, you can do it like this using the MicrocksClient:
var app = orderHostAspireFactory.App; var microcksClient = app.CreateMicrocksClient("microcks"); bool isVerified = await microcksClient.VerifyAsync( "API Pastries", "0.0.1", cancellationToken: TestContext.Current.CancellationToken); Assert.True(isVerified, "API should be verified successfully");
Or check the invocations count like this:
double initialCount = await microcksClient.GetServiceInvocationsCountAsync( "API Pastries", "0.0.1", cancellationToken: TestContext.Current.CancellationToken); // ... perform your API calls ... double finalCount = await microcksClient.GetServiceInvocationsCountAsync( "API Pastries", "0.0.1", cancellationToken: TestContext.Current.CancellationToken); Assert.Equal(initialCount + expectedCalls, finalCount);
If you want to ensure that your application under test is conformant to an OpenAPI contract (or other type of contract), you can launch a Microcks contract/conformance test using Aspire's distributed application model and MicrocksClient integration.
For container-to-host communication, use GetEndpointForNetwork to retrieve an endpoint URL accessible from the Aspire container network, allowing Microcks (running in a container) to reach your application under test.
Prerequisites:
- Set the
ASPIRE_ENABLE_CONTAINER_TUNNELenvironment variable totruein your launch profile or environment.
Note: The universal container-to-host communication is currently an experimental feature and needs to be enabled via environment variable. This fixes long-standing issues with container-to-host communication (issue #6547).
Example in launchSettings.json:
{
"profiles": {
"YourTestProject": {
"environmentVariables": {
"ASPIRE_ENABLE_CONTAINER_TUNNEL": "true"
}
}
}
}Usage:
[Fact] public async Task TestOpenApiContract() { // Arrange var app = _fixture.App; // Use GetEndpointForNetwork with the container network context so that Microcks (running in a container) // can access the order-api service from the Aspire container network Uri endpoint = app.GetEndpointForNetwork("order-api", KnownNetworkIdentifiers.DefaultAspireContainerNetwork); TestRequest request = new() { ServiceId = "Order Service API:0.1.0", RunnerType = TestRunnerType.OPEN_API_SCHEMA, TestEndpoint = $"{endpoint.Scheme}://{endpoint.Host}:{endpoint.Port}/api", }; var microcksClient = app.CreateMicrocksClient("microcks"); var testResult = await microcksClient.TestEndpointAsync(request, TestContext.Current.CancellationToken); // Assert // You may inspect complete response object with following: var json = JsonSerializer.Serialize(testResult, new JsonSerializerOptions { WriteIndented = true }); testOutputHelper.WriteLine(json); Assert.True(testResult.Success); Assert.False(testResult.InProgress, "Test should not be in progress"); Assert.Single(testResult.TestCaseResults); }
Note:
KnownNetworkIdentifiers.DefaultAspireContainerNetworkrefers to the default Aspire container network (aspire.dev.internal).
You can retrieve and inspect exchanged messages for advanced business conformance validation. Here is an example that matches the test code:
var messages = await microcksClient.GetMessagesForTestCaseAsync(testResult, "POST /orders", TestContext.Current.CancellationToken); foreach (var message in messages) { if ("201".Equals(message.Response.Status)) { var responseDocument = JsonDocument.Parse(message.Response.Content); var requestDocument = JsonDocument.Parse(message.Request.Content); var requestProductQuantities = requestDocument.RootElement.GetProperty("productQuantities"); var responseProductQuantities = responseDocument.RootElement.GetProperty("productQuantities"); Assert.Equal(requestProductQuantities.GetArrayLength(), responseProductQuantities.GetArrayLength()); for (int i = 0; i < requestProductQuantities.GetArrayLength(); i++) { var reqProductName = requestProductQuantities[i].GetProperty("productName").GetString(); var respProductName = responseProductQuantities[i].GetProperty("productName").GetString(); Assert.Equal(reqProductName, respProductName); } } }
Note:
- With Aspire, endpoint discovery and Microcks integration are handled automatically. You do not need to manually expose ports or refactor your hosting model as with classic Testcontainers usage.
- Always ensure endpoint names (e.g., "order-api" or "Order-Api") match your distributed application configuration.
- Use
TestContext.Current.CancellationTokenfor async test cancellation, and consider logging the serialized test result for easier debugging.
The Microcks Aspire extension supports essential features of Microcks:
- Mocking of REST APIs using different kinds of artifacts,
- Contract-testing of REST APIs using
OPEN_API_SCHEMArunner/strategy, - Mocking and contract-testing of SOAP WebServices,
- Mocking and contract-testing of GraphQL APIs,
- Mocking and contract-testing of gRPC APIs.
With Aspire, all these features are automatically available when you add the Microcks resource to your distributed application. The integration handles the orchestration and networking automatically.
You can configure additional features directly in your AppHost, to support more advanced use-cases like AsyncAPI contract-testing or Postman contract-testing, we introduced dedicated extension methods for the MicrocksBuilder that allow managing additional Microcks services.
Different levels of API contract testing in the Inner Loop with Testcontainers and available in Microcks .NET Aspire!
var microcks = builder.AddMicrocks("microcks") .WithMainArtifacts("pastry-orders-asyncapi.yml") // Additional configuration can be added here .WithPostmanRunner(); // Enables Postman contract-testing support
For Postman contract-testing, you can use the same TestRequest pattern with the MicrocksClient:
var microcksClient = app.CreateMicrocksClient("microcks"); var testRequest = new TestRequest { ServiceId = "API Pastries:0.0.1", RunnerType = TestRunnerType.POSTMAN, TestEndpoint = $"{app.GetEndpoint("my-api")}/api", Timeout = TimeSpan.FromSeconds(3) }; TestResult testResult = await microcksClient.TestEndpointAsync(testRequest, TestContext.Current.CancellationToken);
If you want to configure Postman runner specific settings, you can do it when adding the Postman runner to the Microcks resource:
var microcks = builder.AddMicrocks("microcks") .WithPostmanRunner(postmanBuilder => { // Customize Postman runner settings postmanBuilder.WithEnvironment("MY_ENV_VAR", "sample"); });
Note: With Aspire, the complexity of managing multiple containers and networks is abstracted away. The distributed application model handles service discovery, networking, and lifecycle management automatically.
Async APIs can also be mocked and contract-tested using Microcks with Aspire. You can import AsyncAPI artifacts and use the MicrocksClient to validate message exchanges.
This feature requires to be explicitly enabled when adding the Microcks resource.
It's done by calling the WithAsyncFeature() method as shown below:
var kafkaBuilder = Builder.AddKafka("kafka") .WithKafkaUI(); var microcksBuilder = builder.AddMicrocks("microcks") .WithMainArtifacts("pastry-orders-asyncapi.yml") .WithAsyncFeature(minion => { minion.WithKafkaConnection(kafkaBuilder, 9093); });
As you can see, we inject the KafkaBuilder into the minion to ensure it can connect properly.
Once started, you can retrieve mock topics from the MicrocksAsyncMinionResource for different
supported protocols (WebSocket, Kafka, etc.). Here's how to consume messages sent by the Microcks Async Minion:
// Retrieve MicrocksAsyncMinionResource from application var appModel = app.Services.GetRequiredService<DistributedApplicationModel>(); var microcksAsyncMinionResource = appModel.GetContainerResources() .OfType<MicrocksAsyncMinionResource>() .Single(); // Get the Kafka topic for mock messages string kafkaTopic = microcksAsyncMinionResource .GetKafkaMockTopic("Pastry orders API", "0.1.0", "SUBSCRIBE pastry/orders"); // Subscribe to the topic and consume messages consumer.Subscribe(kafkaTopic); var consumeResult = consumer.Consume(TimeSpan.FromMilliseconds(5000));
Using contract-testing techniques on Asynchronous endpoints may require a different style of interacting with the Microcks container. For example, you may need to:
- Start the test making Microcks listen to the target async endpoint,
- Activate your System Under Tests so that it produces an event,
- Finalize the Microcks tests and actually ensure you received one or many well-formed events.
For that you can use the MicrocksClient which provides a TestEndpointAsync(TestRequest request) method that returns a Task<TestResult>.
Once invoked, you may trigger your application events and then await the future result to assert like this:
var testRequest = new TestRequest { ServiceId = "Pastry orders API:0.1.0", RunnerType = TestRunnerType.ASYNC_API_SCHEMA, TestEndpoint = "kafka://kafka:9093/pastry-orders", Timeout = TimeSpan.FromSeconds(5) }; var microcksClient = app.CreateMicrocksClient("microcks"); // Start the test, making Microcks listen to the endpoint var taskTestResult = microcksClient.TestEndpointAsync(testRequest, cancellationToken); // Wait a bit to let the test initialize await Task.Delay(750, cancellationToken); // Produce your events to the Kafka topic producer.Produce("pastry-orders", new Message<string, string> { Key = Guid.NewGuid().ToString(), Value = yourMessage }); // Now retrieve the final test result and assert TestResult testResult = await taskTestResult; Assert.True(testResult.Success);
In addition, you can use the GetEventMessagesForTestCaseAsync() method to retrieve the events received during the test. This is particularly useful for inspecting message content and validating business logic:
// Retrieve event messages for the failing test case List<UnidirectionalEvent> events = await microcksClient.GetEventMessagesForTestCaseAsync( testResult, "SUBSCRIBE pastry/orders", TestContext.Current.CancellationToken); // Inspect the events Assert.True(events.Count >= 1); // Check event message content foreach (var eventItem in events) { Assert.NotNull(eventItem.EventMessage); var messageContent = eventItem.EventMessage.Content; // Parse and validate message structure var jsonDocument = JsonDocument.Parse(messageContent); var root = jsonDocument.RootElement; // Validate required fields Assert.True(root.TryGetProperty("id", out _)); Assert.True(root.TryGetProperty("customerId", out _)); Assert.True(root.TryGetProperty("productQuantities", out _)); }
This allows developers to perform detailed validation of the async messages exchanged during contract testing.
This section lists the features related to Microcks initialization, usage and testing.
| Feature | Support |
|---|---|
| Secret creation | ❌ |
| Snapshot restoration | ✅ |
| Local files (primary) | ✅ |
| Local files (secondary) | ✅ |
| Remote urls (primary) | ✅ |
| Remote urls (secondary) | ❌ |
| Remote urls with Secret | ❌ |
| Enable DEBUG log | ✅ |
| Feature | Support |
|---|---|
| REST endpoints | ✅ |
| Soap endpoints | ✅ |
| GraphQL endpoints | ✅ |
| gRPC endpoints | ✅ |
| Invocation verification | ✅ |
| Get invocation stats | ✅ |
| Feature | Support |
|---|---|
| OpenAPI conformance | ✅ |
| Soap conformance | ✅ |
| GraphQL conformance | ✅ |
| gRPC conformance | ✅ |
| Postman conformance | ✅ |
| AsyncAPI conformance | ✅ |
| Get TestCase messages | ✅ |
| Protocol | Support |
|---|---|
| Kafka | ✅ |
| WebSocket | ✅ |
| RabbitMQ | ❌ |
| MQTT | ❌ |
| AMQP | ❌ |
| NATS | ❌ |
| Google PubSub | ❌ |
| Amazon SQS | ❌ |
| Amazon SNS | ❌ |