Creating Unit Tests For Azure Functions

Introduction

 
Service Bus Trigger Azure functions are functions that get started whenever we receive a message on the service bus. These functions are generally useful whenever we want to get some data from a third party or external applications into our applications. Third-party applications send the message to a service bus queue of our application, so whenever a message is received in the queue, these functions will be triggered and we implement our logic to process that message.
 
Below is a small function I have created for getting customer data from other applications and inserting it into my data.
  1. using Microsoft.Azure.ServiceBus;  
  2. using Microsoft.Azure.ServiceBus.Core;  
  3. using Microsoft.Azure.WebJobs;  
  4. using Newtonsoft.Json;  
  5. using System;  
  6. using System.Text;  
  7. using System.Threading.Tasks;  
  8. using Domain.Repositories;  
  9. using Domain.DomainDTO;  
  10. namespace AzureFunctionsUnitTesting {  
  11.     public class ContentProcessor {  
  12.         private readonly ICustomerRepository _customerRepository;  
  13.         public ContentProcessor(ICustomerRepository customerRepository) {  
  14.                 _customerRepository = customerRepository;  
  15.             }  
  16.             [FunctionName("ContentProcessor")]  
  17.         public async Task Run([ServiceBusTrigger("contentmessage", Connection = "ServiceBusConnectionString")] Message message, MessageReceiver messageReceiver) {  
  18.             try {  
  19.                 var messageBody = Encoding.UTF8.GetString(message.Body);  
  20.                 var content = JsonConvert.DeserializeObject < CustomerDto > (messageBody);  
  21.                 await _customerRepository.InsertAsync(content);  
  22.             } catch (Exception ex) {}  
  23.         }  
  24.     }  
  25. }  
You need to provide the queue name and service bus connection string as parameters for the function. In this function, I got the message from queue which is a Json object and I have deserialized into my Dto model and trying to insert it into my Db.
 
So I have my function here, but how do I know whether my function will work when I publish this function? To make sure that the function has no defects in it, we will be creating a unit test method for Azure functions. Also, most importantly if you have your unit tests covered, any breaking change in our system can be detected by running our test methods. When we start developing by test driven development, it will boost the confidence of a developer on his code.
 

Unit Test for Azure Function

 
At first, I will be creating a base class for my tests where I will be mocking my Db Context, ServiceBus connection string etc which will be used common across my tests.
  1. using Autofac;  
  2. using Domain;  
  3. using Microsoft.Azure.ServiceBus;  
  4. using Microsoft.Azure.ServiceBus.Core;  
  5. using Microsoft.EntityFrameworkCore;  
  6. using Microsoft.EntityFrameworkCore.Diagnostics;  
  7. using System;  
  8. using System.IO;  
  9. using System.Text;  
  10. namespace AzureFunctionsUnitTesting {  
  11.     public class TestsBase {  
  12.         public DevelopmentDbContext _context;  
  13.         protected MessageReceiver _messageReceiver;  
  14.         public TestsBase() {  
  15.             var options = new DbContextOptionsBuilder < DevelopmentDbContext > ().UseInMemoryDatabase(databaseName: $ "DevelopmentDb{Guid.NewGuid()}").ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning)).Options;  
  16.             _context = new DevelopmentDbContext(options);  
  17.             var containerBuilder = new ContainerBuilder();  
  18.             var cn = "Endpoint=sb://commoncomponentsqaus.servicebus.windows.net/;SharedAccessKeyName=ClientKey;SharedAccessKey=--------------";  
  19.             var connectionString = new ServiceBusConnectionStringBuilder(cn);  
  20.             connectionString.EntityPath = "Test";  
  21.             _messageReceiver = new MessageReceiver(connectionString);  
  22.         }  
  23.         internal Message LoadMessage(string fileName) {  
  24.             try {  
  25.                 var path = AppDomain.CurrentDomain.BaseDirectory + "Json\\" + fileName;  
  26.                 var json = File.ReadAllText(path);  
  27.                 var bytes = Encoding.UTF8.GetBytes(json);  
  28.                 var message = new Message(bytes);  
  29.                 return message;  
  30.             } catch (Exception ex) {  
  31.                 string g = ex.Message;  
  32.                 var message = new Message();  
  33.                 return message;  
  34.             }  
  35.         }  
  36.     }  
  37. }  
Now I will be writing my unit test method by inheriting the Testsbase class.
 
Below is piece of code for my Unit test of Azure function. I have a mock Json Object(CustomerMessage.Json)
  1. {  
  2.     "id": 1,  
  3.     "CustomerName""Test User",  
  4.     "Country""India",  
  5.     "JoiningDate""28-09-2020",  
  6.     "PrimeUser"false  
  7. }  
I will initializing an object of my function and I have a mock db context. I will sending the Json object in the form of a message. I will run the function and the function will process the message Object I have sent. As our function is to check the records got inserted or not, I will check the count of records in domain I have mocked up.
  1. using Domain.Repositories;  
  2. using Microsoft.VisualStudio.TestTools.UnitTesting;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5. namespace AzureFunctionsUnitTesting {  
  6.     [TestClass]  
  7.     public class ContentProcessorTests: TestsBase {  
  8.         [TestMethod]  
  9.         public async Task Insert_Countries_Into_Db() {  
  10.             //Arrange  
  11.             var message = LoadMessage("CustomerMessage.json");  
  12.             var customerRepository = new CustomerRepository(_context);  
  13.             var  
  14.             function = new ContentProcessor(customerRepository);  
  15.             //Check the count in table to be zero  
  16.             Assert.AreEqual(0, _context.Customers.Count());  
  17.             //Act  
  18.             await  
  19.             function.Run(message, _messageReceiver);  
  20.             //Assert  
  21.             //After Inserting check the count of records in table is 1  
  22.             var dbCount = _context.Customers.Count();  
  23.             Assert.AreEqual(1, dbCount);  
  24.         }  
  25.     }  
  26. }  
 I hope this article helps in writing unit tests for your Azure functions.