I want to perform integration tests which involve interaction with service bus. I have noticed that some messages are not sent, even though no exception gets thrown. I am using a free tier of ASB.
That's the service method responsible for sending the message:
public class ServiceBusMessagingSender<T> : IMessagingSender<T> where T : IMessage
{
private readonly string _connectionString = Environment.GetEnvironmentVariable("SERVICE_BUS_CONNECTION_STRING_SENDER");
private readonly ServiceBusSender _sender;
private readonly IMessageSerializer<T> _messageSerializer;
public ServiceBusMessagingSender(string queueName, IMessageSerializer<T> messageSerializer, string connectionString=null)
{
_messageSerializer = messageSerializer;
_connectionString ??= connectionString;
var client = new ServiceBusClient(_connectionString);
this._sender = client.CreateSender(queueName);
}
public void SendMessage(T message)
{
var serviceBusMessage = _messageSerializer.Serialize(message);
_sender.SendMessageAsync(serviceBusMessage).GetAwaiter().GetResult();
}
This method is then called in tests in NUnit suite:
public class EndtoEndTests {
private readonly ServiceBusMessagingSender<DataRequestDto> _messagingSender = new(RequestsQueue, new MessageSerializer<DataRequestDto>(), WriterConnectionString);
[Test]
public void GoodTypes()
{
//...
//WHEN
var request = new GoodTypesRequest()
{
RequestTimeStamp = DateTime.Now,
RequestType = RequestType.GoodTypes
};
_messagingSender.SendMessage(request );
///...
}
}
I am using the following versions of packages for ASB:
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.2.0" />
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="5.1.3" />
You are calling a Async method inside a void so you are ending up in a race condition of if the send can complete before the function closes.
Change your function to a Task rather than void and the problem should go away.
You also might want to change _sender.SendMessageAsync(serviceBusMessage).GetAwaiter().GetResult();
to
await _sender.SendMessageAsync(serviceBusMessage); for easier to read code.