In the world of microservices, two communication patterns dominate: synchronous REST APIs and asynchronous message brokers. While both serve different purposes, testing them presents unique challenges and approaches.
In this post, we’ll explore how to test message brokers in microservice architectures, compare that process to testing REST APIs, and walk through some example code in C# using tools like Apache ActiveMQ and ASP.NET Core.
1. REST vs Message Broker
1.1 REST APIs (Synchronous)
- Request-response pattern.
- Service A calls Service B and waits for the response.
- Easy to trace and debug.
1.2 Message Brokers (Asynchronous)
- Service A publishes an event to a broker (e.g., RabbitMQ, Kafka, ActiveMQ).
- One or more services consume the message and act on it.
- Promotes loose coupling and scalability.
1.3 Message Broker vs REST API testing
| Feature | REST API | Message Broker |
| Communication Style | Synchronous (HTTP) | Asynchronous (AMQP, Kafka, etc.) |
| Test Complexity | Lower – easier to test via HTTP clients | Higher – needs broker setup and message assertion |
| Isolation | Easier to isolate endpoints | Harder to isolate consumers |
| Observability | Straightforward with status codes, logs | Requires message tracing and correlation IDs |
| Tooling | HttpClient, Postman, WireMock, Swagger | TestContainers, Embedded brokers, mocks, or fakes |
| Failure Simulation | HTTP status codes, timeouts | Simulate dropped, malformed, or duplicate messages |
3. Example
Let’s break it down into examples with code.
3.1 REST API Integration Test (ASP.NET Core)
Controller
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
[HttpPost]
public IActionResult Create(Order order)
{
// Logic to create order
return Ok(new { Message = "Order created." });
}
}
Integration Test
public async Task CreateOrder_ShouldReturnOk()
{
var client = _factory.CreateClient();
var response = await client.PostAsJsonAsync("/api/orders", new { Id = 1, Item = "Book" });
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<ResponseModel>();
Assert.Equal("Order created.", result.Message);
}
🟢 Simple, fast, and works with TestServer or a real app.
3.2 Testing ActiveMQ Message Consumer
Consumer Logic
public class OrderMessageConsumer
{
public void OnMessage(ITextMessage message)
{
var content = JsonSerializer.Deserialize<Order>(message.Text);
Console.WriteLine($"Processed Order: {content.Id}");
// Save to DB or trigger workflow
}
}
Test Setup with Apache.NMS
public void Consumer_ShouldProcessOrderMessage()
{
var factory = new ConnectionFactory("tcp://localhost:61616");
using var connection = factory.CreateConnection();
connection.Start();
using var session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
var destination = session.GetQueue("order.queue");
var producer = session.CreateProducer(destination);
var orderJson = JsonSerializer.Serialize(new Order { Id = 1, Item = "Book" });
var message = session.CreateTextMessage(orderJson);
producer.Send(message);
// Simulate consumer
var consumer = new OrderMessageConsumer();
consumer.OnMessage(message); // inject and assert logic inside
// You’d assert on side effects (e.g., DB entries, logs, etc.)
}
🟠 More involved: requires a running broker or container, and asserts behavior indirectly.
4. Best Practices for Testing Message Brokers
- ✅ Use Dockerized brokers (e.g., via TestContainers or docker-compose) in integration tests.
- ✅ Make your message handlers testable independently of the broker.
- ✅ Use contract tests (e.g., AsyncAPI or schema validation) to ensure message format compatibility.
- ✅ Include DLQ and retry behavior in your tests.
- ✅ Track messages using correlation IDs to verify end-to-end flow.
🔁 When to Use Each Testing Approach
| Scenario | Use REST Testing | Use Broker Testing |
| Verifying CRUD API | ✅ | ⛔ |
| Triggering workflows via events | ⛔ | ✅ |
| Public API integration | ✅ | ⛔ |
| Internal service communication | Maybe – for commands | ✅ – for events, background jobs |
| High-throughput, async communication | ⛔ | ✅ |
5. Conclusion
REST APIs are easier to test and better suited for immediate results and user-facing features. But when your architecture is event-driven, message brokers become central—and testing them effectively is critical to ensuring system reliability.
In the world of microservices, two communication patterns dominate: synchronous REST APIs and asynchronous message brokers. While both serve different purposes, testing them presents unique challenges and approaches.
In this post, we’ll explore how to test message brokers in microservice architectures, compare that process to testing REST APIs, and walk through some example code in C# using tools like Apache ActiveMQ and ASP.NET Core.