Search code examples
c#.net-coreazure-functionsxunitservicebus

Moq Service Bus using xUnit in Azure Function


I have Azure Function which implements the HTTP Triggers and Service Bus. I have managed to complete xUnits implementation for Http Response but not sure how I mock Azure Service Bus. I don't want the code actual create Service Bus Message in the Queue.

 [FunctionName("MyFunction1")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = "POST")] HttpRequest req
        ,[ServiceBus("providerexemptionreceivednotification", Connection = "ProviderExemptionReceivedNotification")] IAsyncCollector<Message> servicebusMessage
        )
    {
         //code
         await servicebusMessage.AddAsync(ringGoExemptionMessage); //throw Null exception: 
    }

Error

enter image description here

xUnit Test

private readonly Mock<IAsyncCollector<Message>> servicebusMessage;

[Fact]
public void 
Function_ShouldReturn_SuccessResponseResultObject_WhenSuccess()
{
        //Arrange
        var fixture = new Fixture();

        var ringGoTransaction = GetRingGoTestData();

        Mock<HttpRequest> mockHttpRequest = CreateMockRequest(ringGoTransaction);

        var providerLocationDataMoq = (1, fixture.Create<ProviderLocation>());

        providerExemptionServiceMoq.Setup(x => x.GetProviderLocation(13, "222")).ReturnsAsync(providerLocationDataMoq);

        //Assert
          var actualResult = sut.Run(mockHttpRequest.Object, (IAsyncCollector<Microsoft.Azure.ServiceBus.Message>)servicebusMessage.Object);  //???????????

        //Act
 }

Test Helper Class

private static Mock<HttpRequest> CreateMockRequest(object body)
{
        var memoryStream = new MemoryStream();
        var writer = new StreamWriter(memoryStream);

        var json = JsonConvert.SerializeObject(body);

        writer.Write(json);
        writer.Flush();

        memoryStream.Position = 0;

        var mockRequest = new Mock<HttpRequest>();
        mockRequest.Setup(x => x.Body).Returns(memoryStream);
        mockRequest.Setup(x => x.ContentType).Returns("application/json");

        return mockRequest;
 }

mock service bus error

enter image description here


Solution

  • I was not seeing where you mocked IAsyncCollector<Message>.

    It looks like an interface

    public interface IAsyncCollector<in T>
    {
        /// <summary>
        /// Adds an item to the <see cref="IAsyncCollector{T}"/>.
        /// </summary>
        /// <param name="item">The item to be added.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>A task that will add the item to the collector.</returns>
        Task AddAsync(T item, CancellationToken cancellationToken = default(CancellationToken));
    
        /// <summary>
        /// Flush all the events accumulated so far. 
        /// This can be an empty operation if the messages are not batched. 
        /// </summary>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns></returns>
        Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken));
    }
    

    Source

    so should be simple enough with new Mock<IAsyncCollector<Message>>() and setting up the members used to exercise the test

    For example

    [Fact]
    public async Task Function_ShouldReturn_SuccessResponseResultObject_WhenSuccess() {
        //Arrange
    
        //... removed for brevity
    
        Mock<IAsyncCollector<Message>> servicebusMessage = new Mock<IAsyncCollector<Message>>();
        servicebusMessage
            .Setup(_ => _.AddAsync(It.IsAny<Message>(), It.IsAny<CancellationToken>()))
            .Returns(Task.CompletedTask);
    
        //Act
        await sut.Run(mockHttpRequest.Object, servicebusMessage.Object);  
    
        //Assert
    
        //...
    }
    

    Given the asynchronous nature of the subject under test, note that the test case has also been made asynchronous.