I have a HttpTrigger function which schedules a new orchestration.
This function has a "[DurableClient] DurableTaskClient starter" input parameter. After scheduling the new orchestration, I use the starter.CreateCheckStatusResponse(req, instanceId) to return as response for the http request.
DurableTaskClient I can easily mock because it is an abstract class with abstract methods.
But CreateCheckStatusResponse is an extension method in src/Worker.Extensions.DurableTask/DurableTaskClientExtensions.cs.
When this is called with the DurableTaskClient mock, the GetQueryParams method will always return null, because the client is not a FunctionsDurableTaskClient. This gives a NullReferenceException, because the BuildUrl function in the SetHeadersAndGetPayload method tries to do a foreach on that null result from GetQueryParams.
Expected behavior
Some way to create a unittest for a function with uses the CreateCheckStatusResponse.
Actual behavior
Throws NullReferenceException
Relevant source code snippets
private static object SetHeadersAndGetPayload(
DurableTaskClient client, HttpRequestData request, HttpResponseData response, string instanceId)
{
static string BuildUrl(string url, params string?[] queryValues)
{
bool appended = false;
foreach (string? query in queryValues)
{
if (!string.IsNullOrEmpty(query))
{
url = url + (appended ? "&" : "?") + query;
appended = true;
}
}
return url;
}
// TODO: To better support scenarios involving proxies or application gateways, this
// code should take the X-Forwarded-Host, X-Forwarded-Proto, and Forwarded HTTP
// request headers into consideration and generate the base URL accordingly.
// More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded.
// One potential workaround is to set ASPNETCORE_FORWARDEDHEADERS_ENABLED to true.
string baseUrl = request.Url.GetLeftPart(UriPartial.Authority);
string formattedInstanceId = Uri.EscapeDataString(instanceId);
string instanceUrl = $"{baseUrl}/runtime/webhooks/durabletask/instances/{formattedInstanceId}";
string? commonQueryParameters = GetQueryParams(client);
response.Headers.Add("Location", BuildUrl(instanceUrl, commonQueryParameters));
response.Headers.Add("Content-Type", "application/json");
return new
{
id = instanceId,
purgeHistoryDeleteUri = BuildUrl(instanceUrl, commonQueryParameters),
sendEventPostUri = BuildUrl($"{instanceUrl}/raiseEvent/{{eventName}}", commonQueryParameters),
statusQueryGetUri = BuildUrl(instanceUrl, commonQueryParameters),
terminatePostUri = BuildUrl($"{instanceUrl}/terminate", "reason={{text}}", commonQueryParameters),
suspendPostUri = BuildUrl($"{instanceUrl}/suspend", "reason={{text}}", commonQueryParameters),
resumePostUri = BuildUrl($"{instanceUrl}/resume", "reason={{text}}", commonQueryParameters)
};
}
private static ObjectSerializer GetObjectSerializer(HttpResponseData response)
{
return response.FunctionContext.InstanceServices.GetService<IOptions<WorkerOptions>>()?.Value?.Serializer
?? throw new InvalidOperationException("A serializer is not configured for the worker.");
}
private static string? GetQueryParams(DurableTaskClient client)
{
return client is FunctionsDurableTaskClient functions ? functions.QueryString : null;
}
Known workarounds
None
App Details
Durable Functions extension version (e.g. v1.8.3): 1.1.3 (Microsoft.Azure.Functions.Worker.Extensions.DurableTask)
Description
I have a HttpTrigger function which schedules a new orchestration. This function has a "[DurableClient] DurableTaskClient starter" input parameter. After scheduling the new orchestration, I use the starter.CreateCheckStatusResponse(req, instanceId) to return as response for the http request.
DurableTaskClient I can easily mock because it is an abstract class with abstract methods. But CreateCheckStatusResponse is an extension method in src/Worker.Extensions.DurableTask/DurableTaskClientExtensions.cs. When this is called with the DurableTaskClient mock, the GetQueryParams method will always return null, because the client is not a FunctionsDurableTaskClient. This gives a NullReferenceException, because the BuildUrl function in the SetHeadersAndGetPayload method tries to do a foreach on that null result from GetQueryParams.
Expected behavior
Some way to create a unittest for a function with uses the CreateCheckStatusResponse.
Actual behavior
Throws NullReferenceException
Relevant source code snippets
Known workarounds
None
App Details