Quite a number of my projects involve talking to RabbitMQ, and to help check things work as expected, I often have a number of integration tests which talk to a local RabbitMQ instance.
While this is fine for tests being run locally, it does cause problems with the build servers - we don’t want to install RabbitMQ on there, and we don’t typically want the build to be dependent on RabbitMQ.
To solve this I created a replacement FactAttribute
which can check if RabbitMQ is available, and skip tests if it is not.
This attribute works with a single host, and will only check for the host actually being there on its first connection.
public class RequiresRabbitFactAttribute : FactAttribute
{
private static bool? _isAvailable;
public RequiresRabbitFactAttribute(string host)
{
if (_isAvailable.HasValue == false)
_isAvailable = CheckHost(host);
if (_isAvailable == false)
Skip = $"RabbitMQ is not available on {host}.";
}
private static bool CheckHost(string host)
{
var factory = new ConnectionFactory
{
HostName = host,
RequestedConnectionTimeout = 1000;
};
try
{
using (var connection = factory.CreateConnection())
{
return connection.IsOpen;
}
}
catch (Exception)
{
return false;
}
}
}
I was planning on using a dictionary, keyed by host to store the availability, but realized that I always use the same host throughout a test suite.
The reason for passing the host name in via the ctor rather than using a constant is that this usually resides within a generic “rabbitmq helpers” type assembly, and is used in multiple projects.