Practical ASP.NET

Testing Precompiled Azure Functions Locally with Storage Emulator

If you're coding Azure Functions in Visual Studio 2017 to work with Azure Storage, one tool that can assist when running functions locally is the Microsoft Azure Storage Emulator, as shown in this hands-on tutorial.

With the newer releases of Visual Studio 2017, you can create Azure Functions from within the IDE using the same techniques (such as unit testing) as other types of .NET projects.

Alongside Visual Studio 2017, the local functions runtime lets you host and run functions locally for development, debugging and testing purposes. If the functions you are developing use Azure Storage, one tool that can assist when running functions locally is the Microsoft Azure Storage Emulator.

The Storage Emulator simulates the cloud Azure Queue, Blob and Table storage services on your local development machine. The emulator is for development purposes only and is not designed for hosting these services for production use.

The Storage Emulator can downloaded as a standalone installer (clicking link initiates download) or as part of the Microsoft Azure SDK.

It should be noted that the Storage Emulator is only an emulator and does not exactly replicate the Azure cloud versions of these services. For example the current version of the emulator only supports blob sizes up to 2 GB and for Table storage the total maximum row size is limited to less than 1 MB. You can read more about all the differences in the documentation. This means that the Storage Emulator may not always provide all the capabilities you need to test locally; in these cases you would still need to create and connect to a development storage account in Azure.

Using the Storage Emulator from a Azure Function
Assuming you have the latest version of Visual Studio 2017 and the "Azure Functions and Web Jobs Tools" extension is installed, a new Azure Functions project type can created in Visual Studio (see Figure 1).

Creating a new Azure Functions Project in Visual Studio
[Click on image for larger view.] Figure 1. Creating a new Azure Functions Project in Visual Studio

When you add a new Azure Functions project, you will be taken though a creation wizard that allows you to create an empty project or add an initial function (such as an HTTP-triggered function). As part of this wizard you can select the storage account to be used for development. In the dropdown you can select Storage Emulator so you don't need a cloud Storage Account or even an Azure account (see Figure 2).

Choosing the Storage Emulator
[Click on image for larger view.] Figure 2. Choosing the Storage Emulator

After clicking OK, the project will be created.

The local.settings.json file contains settings that apply to the local environment. If this file is opened there are two preconfigured settings, one for the storage account to be used for the web jobs dashboard and one for the web jobs storage. If you selected Storage Emulator from the dropdown in Figure 2 these will both be set to "UseDevelopmentStorage=true." This means that if you run the function locally the Storage Emulator will be used.

As an example, a new function can be added to the project using the "Http POST CRUD" function template and the code modified to write a new quote to Table storage as Listing 1 shows.

Listing 1: HTTP Triggered Function Writing to Azure Table Storage

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.WindowsAzure.Storage.Table;

namespace QuoteFunctions
{
  public static class Create
  {
    [FunctionName("Create")]
    public static async Task Run(
      [HttpTrigger(AuthorizationLevel.Function, "post")]HttpRequestMessage req, 
      [Table("quote")]ICollector outTable, 
      TraceWriter log)
    {
      dynamic data = await req.Content.ReadAsAsync<object>();
      string quoteText = data?.quoteText;

      if (quoteText == null)
      {
        return req.CreateResponse(HttpStatusCode.BadRequest, "Please pass quoteText in the request body");
      }

      outTable.Add(new Quote()
      {
        PartitionKey = "Quotes",
        RowKey = Guid.NewGuid().ToString(),
        QuoteText = quoteText
      });
      return req.CreateResponse(HttpStatusCode.Created);
    }

    public class Quote : TableEntity
    {
      public string QuoteText { get; set; }
    }
  }
}

If you try to run the function locally and make a POST to the new quote function you will get an error in the functions runtime window indicating that the Storage Emulator is not running: "Please verify that the Azure Storage Emulator is running. Microsoft.WindowsAzure."

You can start the Storage Emulator from the command line or hit the Windows key and type "storage emulator" and start it from the Start Menu. This will start the Emulator as shown in Figure 3.

Starting the Storage Emulator
[Click on image for larger view.] Figure 3. Starting the Storage Emulator

It may take a few seconds for the Storage Emulator to get started. You can check in the notification area, you should see the icon as shown in Figure 4.

Storage Emulator Running
Figure 4. Storage Emulator Running

Testing the Function Locally
Now if the project is run locally from Visual Studio, the local runtime will start. If an HTTP POST is made to the localhost address of the HTTP function, a new row will be created in the table. Using Visual Studio Cloud Explorer (see Figure 5), and expanding the (Development) node, the "quote" table can be opened (see Figure 6).

Using Cloud Explorer to Examine the Table
Figure 5. Using Cloud Explorer to Examine the Table

The Storage Emulator is a great tool to have in the toolkit when developing Azure Functions, not only does it mean you can work in a disconnected environment, because the storage is local it is quicker than reading and writing to Azure Storage in the cloud.

Row Created
[Click on image for larger view.] Figure 6. Row Created

There are some limitations that you might run into when using the emulator so it's a good idea to read through the documentation before making use of it.

About the Author

Jason Roberts is a Microsoft C# MVP with over 15 years experience. He writes a blog at http://dontcodetired.com, has produced numerous Pluralsight courses, and can be found on Twitter as @robertsjason.

comments powered by Disqus

Featured

Subscribe on YouTube