Azure Functions Unit testing- Mocking azure-storage npm module with Jest

Lakshaykaushik
5 min readMar 9, 2020

100 percent code coverage!! Well thats what we keep hearing from our colleagues and we all aspire for 100 percent code coverage but somewhere deep within ourselves we know that sometimes writing unit test cases for an application takes more time than the actual implementation of business logic!! If at all, 100 percent code coverage was that easy, all our projects would have had the perfect score.

We were writing azure functions and our business logic was dependant on azure-storage accounts- table, blob and queue storage. We had a lot of calls to the storage accounts and to ensure that all key areas of our code were testable it became important that we had to mock the azure-storage npm specifically. What we noticed that there is a lack of information on how to mock the azure-storage npm module in the community and many developers have resorted to setting up Azure storage emulator or Azurite on their local machines- what we thought was not an ideal solution!!. Some developers have used a combination of sinon, chai, mocha and proxy to successfully mock azure-storage npm module. Here we present, mocking of azure-storage npm module by using only Jest!.

But before we do that, let’s see how usually someone would go about writing their index.js file when they are using azure-storage npm module:

As you can see above, there are some problems with this implementation, to describe few:

  1. Our azure function is async and we would need to take some action with the fetched blob in the callback of getBlobToText function. There is no guarantee that whatever is inside the callback function would run before the azure function execution gets finished. But are there any workarounds for this? Yes, make your azure functions non-async. But then you cannot use the sweet functionality of async/await anywhere in your azure function.
  2. How do you test this? So basically whatever actions you need to take after fetching the blob, that needs to go inside the callback function. Even if you make it non-async, you will have a good chunk of business logic going inside the callback. You simply cannot overwrite the implementation of the callback by mocking its response. But then you may ask, why would i mock the callback function? Well that is because like any other function your callback function also needs to be tested or mocked to ensure you are covering all cases.

So this is something you get while testing the above code, without mocking the callback function.

As you can see some part of the code goes untested if we do not mock the implementation of callback function and we cannot overwrite the implementation because a lot of our business logic would reside in the callback function in this approach, What tradeoff do you make? Do you test all cases in your code or you simply mock the implementation of now a critical function? Well you do not need to make a tradeoff! We show you one way of doing this!

In our approach, we had a functions file containing 2 functions to interact with the storage accounts. You can also have all functions which your application is using to interact with the storage accounts in this file.

  1. The first function makes an entry inside azure table
  2. The second function fetches a blob from the storage account

It is a standard implementation of the insertOrReplaceEntity and getBlobToText functions of the azure-storage module, these function can be called using the good old way of try/catch in your index.js file.

But!, what is the problem if we do not wrap the function inside another Promise, what do we lose? Well, doing this makes the code easier to test and it makes the index.js( in which these functions are being called) easier to implement by using the try/catch pattern.

Hey! This even makes testing the index.js file much easier and we can still keep our azure function async. As we have already mocked the internals of our wrapper functions, you can easily mock the InsertToTable directly and have it return a desired response which can be asserted by the test cases you have written to test index.js.

So this pattern gives us 3 wins:

  1. We can easily mock the InsertToTable wrapper function for testing our index.js file. Our index.js depends on the output of wrapper functions. Our index.js file now becomes a simple orchestrator. Testing this is easy!
  2. We can separately mock the functions inside the wrapper function and ensure they have 100 percent code coverage because we have separated the business logic from the call back functions of azure-storage modules. How to mock this in Jest is shown below.
  3. No need to setup Azurite or Azure storage emulator on local machine just to write and execute unit test cases.

Now the main part!, how have we mocked the azure-storage npm module by using only Jest!

Our test.js file contains 4 test cases to test out all positive and negative scenarios.

The four test cases are:

  1. Insert to table storage gives Success.
  2. Insert to table storage gives failure.
  3. Blob is successfully fetched from storage account.
  4. Failed to fetch blob from storage account.

Main points to note in the test.js file are:

  1. We have used Promises, although you can also mock the functions using the callback pattern.
  2. The mocked callback functions of azure-storage can be made to return our desired output which the test cases can consume and assert on.

Below is the test.js file having these 4 test cases.

And here is the 100 percent code coverage for the 2 functions we mocked!!

In case you want to try running the test cases on your machine or run the azure function in your azure subscription, clone my repo: https://github.com/lakshaykaushik/JestMocks.

References:

  1. https://www.npmjs.com/package/azure-storage
  2. https://jestjs.io/docs/en/mock-functions.html.

--

--