Azure Event Grid is a server-less message router. It provides a place for event publishers to send messages to (a topic), and pushes events to interested subscribers (via subscriptions). The question addressed here is: How do we write integration tests for this pub-sub mechanism?
What are we testing?
Integration tests should provide you with confidence your setup is working, preferably run on each change as part of a CI/CD pipeline.
To me, a valuable test would be to ensure we can send an event to Event Grid, and then observe it coming out the other side, to be processed by a subscriber. There are few reasons you may want to do this:
- You want to check that you are setting up your infrastructure correctly
- You can verify the integrity of the event on the subscriber side
The problem
Posting an event to a topic boils down to making a HTTP request to the endpoint exposed by the topic. I think this is a solved problem so I won’t cover the details here.
However, when setting up a subscription to a topic you must provide a webhook endpoint. In production, this is going to be a genuine API that you can’t really just spam when executing integration tests. Of course you could set up your own API and have it execute your test code but that’s a faff, right?
Wouldn’t it be great if we could just set up a subscription and then just “listen” to events being delivered to it? This way we wouldn’t have to set up a genuine API — we would have access to the events by opening up some sort of channel. This where Azure Relay Hybrid Connections provide welcome help.
The key to the solution
Azure Relay 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.
Implementation
Before writing code, we need to actually create the required Azure resources. I’d recommend creating specific resources just for testing purposes. Might seem like a faff that your tests might have to setup up infrastructure just to execute a test but this is no different to having to setup a database just for integration tests, for example.
Setup
We will need:
- A Relay, with a Hybrid Connection — see the docs for creating one. It is simple enough via the Portal UI.
- A Topic to send events to — again, can be done easily enough in the Portal UI. You will need to specify the event schema, which will dictate the shape of the events you send/receive.
- A Subscription, on that topic, that uses the above Hybrid Connection URL as the endpoint. Via the Portal UI navigate to the Topic you just created, add a subscription. You will get the option when specifying the endpoint to select our Hybrid Connection.
This can all be done manually in the UI, or can be automated via something like terraform or the Azure CLI.
Writing the test
If you are using C#, Microsoft provides a client that allows you to open up a connection to the Relay. Once this channel is opened up, it will receive any traffic that comes through (i.e. our events!), which we can then execute some code against. This is really the final piece, giving us the entry point into receiving events and asserting against them, without the overhead of creating a separate API.
Roughly, the code could do something like this:
- Open a connection to the Relay, and start listening
- Post event to the Topic
- Use the connection to observe the incoming event(s), and execute any assertions.
Posting to the topic involves making a HTTP request to the Event Grid Topic endpoint. If you are using C#, you can achieve this easily using the HttpClient class.
For more information on how to interact with the Microsoft.Azure.Relay package, see this article.