I've got a time-triggered Azure Function which I want to test with XUnit and MOQ.
While I know I need to call the Run
method of the class using an instance of the class say funTimeTriggeredObj
where
funTimeTriggered funTimeTriggeredObj = new funTimeTriggered(queueSchedulerMock.Object, telemetryHelperMock.Object)
like
funTimeTriggeredObj.Run(param1, param2, loggerMock.Object)
where
private Mock<ILogger> loggerMock = new Mock<ILogger>()
I'm not sure how should I mock the param1
& param2
which are TimerInfo
and ExecutionContext
objects respectively.
The reason why I'm asking is because neither 'TimerInfo' nor 'ExecutionContext' implements any interface which can be mocked.
Below is my actual function implementation. Any help whatsoever would be highly appreciated.
using System;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
public class funTimeTriggered
{
private string _invocationID;
private readonly IQueueScheduler _queueScheduler;
private readonly ITelemetryHelper _telemetryHelper;
public funTimeTriggered(IQueueScheduler queueScheduler, ITelemetryHelper telemetryHelper)
{
_queueScheduler = queueScheduler;
_telemetryHelper = telemetryHelper;
}
[FunctionName("funTimeTriggered")]
public async Task Run([TimerTrigger("0/10 * * * * *")]TimerInfo myTimer, ExecutionContext context, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
try
{
_invocationID = context.InvocationId.ToString();
await _queueScheduler.SendEventsToServiceBusAndDeleteFromSQS();
}
catch (Exception ex)
{
log.LogError(ex.Message);
_telemetryHelper.LogException(ex);
throw ex;
}
}
}
When executing your Azure Functions, the functions runtime will run your function code with a concrete implementation of these interfaces. For unit testing, you can pass in a mocked version of these interfaces to test your business logic.
Create a timer triggered functionIn your function app, select Functions, and then select + Create. Select the Timer trigger template. Configure the new trigger with the settings as specified in the table below the image, and then select Create. Defines the name of your timer triggered function.
If a function app scales out to multiple instances, only a single instance of a timer-triggered function is run across all instances. It will not trigger again if there is an outstanding invocation is still running.
If there are no undesired effects of using actual instance of those classes and you can actually initialize them then create actual instance and pass them to the function under test.
They do not have to be interfaces or mocked if using the actual instance(s) has no unwanted effects
//Arrange
//...omitted for brevity
var param1 = new TimerInfo(...);
var param2 = = new ExecutionContext {
InvocationId = Guid.NewGuid()
};
//Act
await funTimeTriggeredObj.Run(param1, param2, loggerMock.Object);
//Assert
//...assert expected behavior
And since in this test case the timer is not even used by the function, it can be ignored altogether
//Arrange
//...omitted for brevity
var param1 = default(TimerInfo); //null
var param2 = = new ExecutionContext {
InvocationId = Guid.NewGuid()
};
//Act
await funTimeTriggeredObj.Run(param1, param2, loggerMock.Object);
//Assert
//...assert expected behavior
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With