Unit Test Azure Function with Table Extension in C#

Unit Test Azure Function with Table Extension in C#

Table of Contents

1 Functions
2 Unit Tests

The new webjobs extensions can be used for Azure Table Storage CRUD operations with Azure Functions:

Add nuget package to your Azure Function
nuget.org: Microsoft.Azure.WebJobs.Extensions.Tables

dotnet add package Microsoft.Azure.WebJobs.Extensions.Tables

Please find the complete code at
https://github.com/MarkusMeyer13/azure.functions.tables

1 Functions

Using the TableClient is straight forward.

AddEntityAsync

TableEntity with TableClient:

[FunctionName("Add")]
public static async Task<IActionResult> AddAsync(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = "sample")] HttpRequest req,
    [Table("Sample", Connection = "SampleTableConnection")] TableClient client,
    ILogger log)
{
    var body = await req.ReadAsStringAsync().ConfigureAwait(false);

    var data = JObject.Parse(body);

    var entity = new TableEntity(data["Country"].Value<string>(), data["Company"].Value<string>())
    {
        ["Description"] = data["Description"].Value<string>()
    };

    var result = await client.AddEntityAsync(entity).ConfigureAwait(false);
    log.LogInformation($"Add - added");

    return new NoContentResult();
}

Request-Body:

{
    "Country": "Germany",
    "Company": "Lorem",
    "Description": "Ipsum"
}

DeleteEntityAsync

TableEntity with PartitionKey, RowKey and TableClient:

[FunctionName("Delete")]
public static async Task<IActionResult> DeleteAsync(
    [HttpTrigger(AuthorizationLevel.Function, "delete", Route = "sample/{partitionKey}/{rowKey}")] HttpRequest req,
    [Table("Sample", Connection = "SampleTableConnection")] TableClient client,
    string partitionKey,
    string rowKey,
    ILogger log)
{
    var result = await client.DeleteEntityAsync(partitionKey, rowKey).ConfigureAwait(false);
    log.LogInformation($"Delete - StatusCode: {result.Status}");
    log.LogInformation($"Delete - Content: {result.Content}");

    if (result.Status.Equals(404))
    {
        log.LogInformation($"Delete - not found");
        return new NotFoundResult();
    }

    log.LogInformation($"Delete - deleted");

    return new NoContentResult();
}

2 Unit Tests

The TableClient and the Azure.Response are mocked:

var mockResponse = new Mock<Azure.Response>();
mockResponse.SetupGet(x => x.Status).Returns((int)HttpStatusCode.NotFound);
mockResponse.SetupGet(x => x.Content).Returns(BinaryData.FromString("{\"odata.error\":{\"code\":\"ResourceNotFound\",\"message\":{\"lang\":\"en-US\",\"value\":\"The specified resource does not exist.\\nRequestId:19ab49c9-2002-001c-145f-7d77db000000\\nTime:2022-06-11T06:47:53.2893442Z\"}}}"));

Mock<TableClient> tableClient = new Mock<TableClient>();
tableClient.Setup(_ => _.DeleteEntityAsync(It.IsAny<string>(), It.IsAny<string>(), default, default))
    .ReturnsAsync(mockResponse.Object);

DeleteEntityAsync returns

  • StatusCode: 404
  • Content: {"odata.error":{"code":"ResourceNotFound","message":{"lang":"en-US","value":"The specified resource does not exist.\nRequestId:19ab49c9-2002-001c-145f-7d77db000000\nTime:2022-06-11T06:47:53.2893442Z"}}}
    if the entity is not found.

DeleteEntityAsync returns no content

  • StatusCode: 204
  • Content:
    if the entity is found.