TL;DR - Azure Relay Hybrid Connections allows you to relay all your Azure Event Grid events into your tests so that you can verify that your platform is running smoothly
95% of the credit for this post should go to Sean Feldman whom inspired me to take this route by reading this blog post.
Building applications is always an adventure and one of the most important aspects is testing. This is no different when building event-driven platforms which use components such as Azure Event Grid.
While there are a lot of different test strategies, we will focus on integration testing today. If you want to learn more about testing I recommend reading The Practical Test Pyramid if you are interested.
I'm a strong believer in integration testing, certainly when you are working in the cloud space. They allow you to test that one component of your application and see if they can integrate, hence the name, with one of your dependencies.
When working with Azure Event Grid this is no different - When you send events to Azure Event Grid, how do you know if the process on the other end can successfully deserialize your message and consume it?
It's simple - You don't unless you test it.
This is exactly what we had to do while for Arcus which makes Azure Event Grid development easier. There I had to find a way so that I can verify that everything was still working and this article explains how we've approached it and how we can help you.
What are we trying to test?
Conceptually Azure Event Grid is a serverless event-driven pub/sub offering which allows parties to emit events to a custom topic and others can create a subscription to start receiving those events by providing a webhook endpoint. (more info)
This is where the problem lies - A webhook endpoint to which all our events will be sent. In a real-world scenario, this will be your deployed application which integrates with Azure Event Grid but in our integration tests we cannot do that as they will be running on my laptop, a CI build, etc.
This means that we need to provide a mechanism which is subscribing to our custom topic and relays all events to our tests.
While tools like ngrok allow you to do that they do not fit our needs because:
- They run as a separate process outside of your tests
- They need to be installed on every machine running your tests
The good news is - Azure Relay is precisely what we need.
Enter Azure Relay Hybrid Connections
Azure Relay was initially designed by an incubation team including Clemens Vasters which was running on a machine running under a desk at Microsoft and is now grown to a first-class Azure service providing a ton of hybrid integration scenarios in a secure manner.
The service allows you to expose a public endpoint in your application without having to open up any ports on your side. Clients can simply communicate with Azure Relay which will relay, hence the name, all requests to your application.
Once you understand how this works, you'll actually notice that this is probably used under the hood for a lot of Azure components such as Dev Spaces for AKS, Azure Data Factory Integration Runtime, etc.
Here's a high-level overview of the architecture:
In our scenario, we will are going to create a Relay namespace that contains a Hybrid Connection. That Hybrid Connection will be subscribing to events on our custom Azure Event Grid topic for new events and relay them to our Hybrid Connection clients.
In the context of our testing, we will connect to our Hybrid Connection and start receiving those relayed events via .NET. (docs)
Setting up our testing infrastructure
Time to set up our testing infrastructure!
This is what we need:
- A custom Azure Event Grid topic to send & receive events
- An Azure Relay namespace which has a Hybrid Connection
- A subscription on our custom Azure Event Grid topic for our Hybrid Connection
Our testing infrastructure will look like this:
The best way to do this is by using an ARM template so that you can easily ramp up new people and allows others to easily get started in their subscription as well.
Unfortunately, it looks like you cannot create a subscription for Hybrid Connection endpoints via ARM yet so we'll have to do it manually.
There are a few interesting aspects to note when creating a subscription:
- We can subscribe to specific events based on their type or all events
- You can choose to either receive events which are according to the Event Grid schema (docs) or CloudEvents v0.1 (docs | spec)
- You can filter on events of the same type based on the subject of the event
Subscribe and filter wisely or you'll regret it later on.
That's it, we are ready to write our test!
Writing a test with Azure Relay Hybrid Connection
With our testing infrastructure waiting to be used we can (finally) write our test.
First things first, install the Arcus testing NuGet package:
PM > Install-Package Arcus.EventGrid.Testing
As a next step, we will create the boilerplate for our integration test which will open a new
HybridConnectionsHost for every test and close it when the test finished. This allows us to fully isolate tests.
For our test, I'm using xUnit where I can use
IAsyncLifetime to tie in to the test lifecycle and manage our connection host.
Now that our hybrid connection host is listening we can write our test case which will send, receive and deserialize events.
By using Azure Relay with Hybrid Connections you can very easily set up a testing infrastructure to run all your integration tests which can run on any machine as it does not have any dependencies.
Arcus allows you to benefit from some of the work we’ve done before by just plugging it in your tests. Want to get started? Check our docs!
Want to learn more about Arcus? Check it out on GitHub.
Thanks for reading,