From Service Bus to Storage Queue: A Testing Journey Link to heading
After successfully implementing testcontainers for Azure Service Bus (which I wrote about in my previous post), I found myself working on a new solution that needed Azure Storage Queue instead.
Naturally, I got curious - could I apply the same testing approach? Turns out, yes! But the journey taught me some interesting things about the differences between these two Azure messaging services.
The Starting Point Link to heading
I had already cracked the code for Service Bus testing:
- Testcontainers managing the Service Bus emulator
- Clean Azure Functions with triggers
- Reliable integration tests
- No cloud resources needed for development
The pattern was working beautifully. But now I had a new requirement: Azure Storage Queue.
The Question Link to heading
Could the same testcontainers approach work for Azure Storage Queue? I was motivated to find out because:
- I knew the pain - Testing with real Azure resources is expensive and slow
- I had a pattern - Service Bus testcontainers was working well
- New solution needed it - Couldn’t just skip testing this time
- Curiosity - How different could Storage Queue really be?
The Investigation Link to heading
First discovery: Azure Storage Queue uses Azurite, not a separate emulator like Service Bus.
Azurite is Microsoft’s unified emulator for Azure Storage services - Blob, Queue, and Table storage all in one. This was actually better than I expected!
The testcontainers setup was even cleaner than Service Bus! No config files needed, just start the Azurite container. The container manager handles everything - starting the emulator, exposing the right ports, and providing the connection string.
Even better: Azurite starts faster than the Service Bus emulator. About 5 seconds versus 20 seconds. Small win, but it adds up when you’re running tests frequently.
The Azure Function followed the same clean pattern as Service Bus - a simple trigger attribute, automatic deserialization, and just business logic. No try-catch noise, no manual JSON parsing, no infrastructure code cluttering the function.
Beautiful and focused.
The Pleasant Surprise Link to heading
While implementing this, I discovered something nice: Azure Storage Explorer actually works with Azurite!
This was different from Service Bus where the Service Bus Explorer doesn’t work with the emulator. With Storage Queue, I could:
- Start Azurite locally
- Open Azure Storage Explorer
- Connect to the local emulator
- See the queues, peek messages, inspect everything
This made debugging so much easier.
But I still wanted programmatic inspection for automated testing. The peek operation turned out to be just as clean as Service Bus - fetch messages without consuming them, inspect the properties, verify the content.
The test logs show exactly what’s happening at each step, making it easy to debug when something goes wrong.
Key Differences I Learned Link to heading
Working with both made the differences clear:
Feature | Service Bus | Storage Queue |
---|---|---|
Emulator | Service Bus Emulator | Azurite |
Ports | 5672 (AMQP), 5300 (HTTP) | 10000-10002 (HTTP) |
Config | JSON file required | No pre-config needed |
Startup Time | ~20 seconds | ~5 seconds |
Explorer Tool | Limited support | Full Azure Storage Explorer |
Message Size | Up to 256KB | Up to 64KB |
Protocol | AMQP | HTTP REST API |
The Testing Strategy Link to heading
I ended up with a layered testing approach for both Service Bus and Storage Queue:
Integration Tests - Test queue operations without running the full Azure Functions runtime. Send messages, receive them, verify serialization works.
Inspection Tests - Verify queue state without consuming messages. Peek at what’s in the queue, check message properties, confirm everything is there.
Unit Tests - Test business logic in isolation with mocks. Fast, reliable, no dependencies.
Manual Testing - Full end-to-end with func start
for final verification against real or local emulators.
Each level serves a purpose. Together they give confidence without excessive test time.
The Results Link to heading
After implementing both samples:
✅ Fast feedback - Tests run in seconds, not minutes
✅ No cloud costs - Everything runs locally
✅ Consistent environment - Same setup everywhere
✅ Easy debugging - Visual tools work (especially for Storage Queue)
✅ Comprehensive coverage - Multiple test levels
✅ Production confidence - Caught issues before deployment
What I’d Do Differently Link to heading
Looking back, I should have:
- Started with the shared library - Would have saved refactoring time
- Used immutable builder from the start - Better design, even for tests
- Added the pause-for-exploration feature earlier - Made debugging much easier
But these are minor compared to the value of having reliable, automated testing.
The Code Link to heading
Both complete samples are available:
Each includes:
- Complete Azure Function implementation
- Testcontainers integration
- Comprehensive test suite
- Shared business logic library
- Detailed README with instructions
Final Thoughts Link to heading
Starting with Service Bus and expanding to Storage Queue taught me that the pattern is more important than the technology.
The curiosity to explore Storage Queue after solving Service Bus led to deeper understanding of Azure messaging options and reliable testing approaches.