1
votes

I am starting off with Durable Azure Functions(latest version) and it's unit testing(using x-unit). Below is my trigger function(http triggered):

[FunctionName("funcEventSubscriber")]
public async Task<HttpResponseMessage> HttpStart(
    [HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestMessage req,
    [DurableClient] IDurableOrchestrationClient starter,
    ILogger log)
{
    try
    {
        string instanceId = await starter.StartNewAsync("funcEventOrchestrator", null);
        log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
        return starter.CreateCheckStatusResponse(req, instanceId);
    }
    catch (System.Exception ex)
    {
        _telemetryHelper.LogException(ex);
        throw;
    }
}

And this one is my orchestrator function which kicks-off activity functions:

[FunctionName("funcEventOrchestrator")]
public async Task<List<string>> RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    try
    {
        var outputs = new List<string>();
        var reusultSet = new List<string>();
        outputs = await context.CallActivityAsync<List<string>>("funcActivityA", "");
        foreach (var item in outputs)
        {
            var result = await context.CallActivityAsync<List<TableRegionEntity>>("funcActivityB", item);
            if (result.Count > 0)
            {
                foreach (var data in result)
                {
                    List<string> inputObject = new List<string>();
                    inputObject.Add(data.Subscriber);
                    inputObject.Add(item);
                    reusultSet.Add(await context.CallActivityAsync<string>("funcActivityC", inputObject));
                }
            }
            else
            {
                reusultSet.Add(await context.CallActivityAsync<string>("funcActivityD", item));
            }
        }
        return reusultSet;
    }
    catch (System.Exception ex)
    {
        _telemetryHelper.LogException(ex);
        throw;
    }
}

The unit test method which I've written for my orchestrator function looks something like this:

[Fact]
public async Task Run_returns_list_of_string()
{
    var mockContext = new Mock<IDurableOrchestrationContext>();
    mockContext.Setup(x => x.CallActivityAsync<List<string>>("funcActivityA", "")).ReturnsAsync(funcActivityAOutput);
    mockContext.Setup(x => x.CallActivityAsync<List<TableRegionEntity>>("funcActivityB", inputJsonString)).ReturnsAsync(funcActivityBOutput);
    mockContext.Setup(x => x.CallActivityAsync<string>("funcActivityC", funcActivityCInputObject)).ReturnsAsync(funcActivityCOutput);
    mockContext.Setup(x => x.CallActivityAsync<string>("funcActivityD", inputJsonString)).ReturnsAsync(funcActivityDOutput);

    // Instantiate funcEventSubscriber
    funcEventSubscriber funcEventSubscriberObj = new funcEventSubscriber(telemetryHelperMock.Object);

    // Act
    var result = await funcEventSubscriberObj.RunOrchestrator(mockContext.Object); // call orchestrator fn

    // Assert
    Assert.Equal(3, result.Count);
}

The way I'm setting up mockContext throws an error. This is the error from the first line of mockContext.Setup i.e

mockContext.Setup(x => x.CallActivityAsync<List<string>>("funcActivityA", "")).ReturnsAsync(funcActivityAOutput);`

enter image description here

Where am I going wrong here?

1

1 Answers

1
votes

In your setup, the line in question is suppose to return a List<string>, given that the mocked member is defined as

IDurableOrchestrationContext.CallActivityAsync<TResult>(String, Object) Method

public Task<TResult> CallActivityAsync<TResult> (string functionName, object input);

where

TResult: The return type of the scheduled activity function.

Ensure that the correct return type is being used for the mocked member. That way the correct ReturnsAsync extension can be invoked on the setup

For example

//...

List<string> funcActivityAOutput = new List<string>() {
    //...populate list as needed
}
var mockContext = new Mock<IDurableOrchestrationContext>();
mockContext
    .Setup(x => x.CallActivityAsync<List<string>>("funcActivityA", ""))
    .ReturnsAsync(funcActivityAOutput);

//...