Home > Back-end >  Im not able to mock ServiceBusReceivedMessage and ServiceBusMessageActions
Im not able to mock ServiceBusReceivedMessage and ServiceBusMessageActions

Time:03-01

we want to write unit-test for servicebus message trigger. we are using Azure.Messaging.ServiceBus nuget package

     [FunctionName("serviebustrigger")]
  public async Task Run ([ServiceBusTrigger("xxxxtopic", "xxxxsubscription", Connection = "Abs-Connection", AutoCompleteMessages = false)] ServiceBusReceivedMessage message, ServiceBusMessageActions messageActions)

    {
        _logger.LogInformation($"{nameof(Run)} execution started for MessageId:{{MessageId}}", message.MessageId);
        try
        {
                //some code
             await messageActions.CompleteMessageAsync(message);
        }
        catch (Exception ex)
         {
             await messageActions.DeadLetterMessageAsync(message);
         }
    }

Now I want to write unit test for the above code. But I'm not able mock ServiceBusReceivedMessage and ServiceBusMessageActions as these have Internal Constructor. Can someone suggest me better way to write unit test

CodePudding user response:

There was an oversight with the implementation of ServiceBusMessageActions where the mocking constructor was initially overlooked. This was corrected in v5.2.0 of the extensions package.

With that fix, a parameterless constructor is available to ensure that ServiceBusMessageActions is usable with a mocking framework such as Moq or FakeItEasy. Each of the public members are virtual or settable, the class is not sealed. You should be able to mock using the same approach that you prefer for other types, whether with a mocking framework or inheriting from the class and creating your own mock type, using the model factory to simulate behavior.

For ServiceBusReceivedMessage and other model types that are returned by service operations, the ServiceBusModelFactory is used to create instances for testing purposes.

CodePudding user response:

As I can see from this GitHub Source, add a protected constructor to the ServiceBusMessageActions class to support mocking for test scenarios.

  • Actions performed on ServiceBusMessageActions can be used in place of the MessageReceiver metadata property.

Reference: Refer for the Methods available in ServiceBusMessageActions

Suppose you want to manually handle ServiceBusMessageActions methods like message completion or abandon back to the Service Queue in C# Azure Function with Azure Service Bus, then please visit this SO Thread.

Note: Make Sure, the caller must have access to the MessageReceiver used to retrieve the message.

To get the information and a practical workaround related to Mock Unit Test on the servicebusMessage , please refer [here](https://stackoverflow.com/a/69897648).

For the Practical Workarounds on Unit Tests on Azure Functions bind with Service Bus Trigger, visit this SO Thread which has code related to MessageReceiver Class using CompleteAsync method.

Please check these references which helps to work around:

  1. Unit and Integration test for Azure Function with ServiceBus Trigger
  2. A C# Corner article on Unit Tests related to Azure Functions with ServiceBus Trigger
  3. Is It possible to mock out IMessageReceiver and related classes for Unit Testing in C#
  4. MSFT Doc on Message Settlement - ServiceBusMessageActions
  • Related