Search code examples
c#azureunit-testingazure-functionsmoq

Unit Testing Azure Functions With Dependency Injection


I haven't written any Azure functions in quite a long time, and thought I'd refresh myself today, but I've clearly forgotten how to write appropriate unit tests for them. I have the following Function - it picks a random quote from a list;

public class QuoteFunction
{
    private readonly IQuoteBank _repository;

    public QuoteFunction(IQuoteBank repository)
    {
        _repository = repository;
    }

    [FunctionName("GetQuote")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        Quote quote = _repository.getQuote();
        return new OkObjectResult(quote);
    }
}

and it uses dependency injection to obtain the list of quotes - I have the following in Startup;

public override void Configure(IFunctionsHostBuilder builder)
{
    builder.Services.AddSingleton<IQuoteBank, QuoteBank>();
    builder.Services.AddLogging();
}

which is injected into the constructor of the Function. as shown in the first snippet.

What I am struggling with is how I can use Moq to force the quote (which is randomly selected) to be consistent. I know I can mock the Interface IQuoteBank - but there is no where I can pass this mock object into the Run method.

So what I want to know is how I can pass a mock object to make the same quote be produced for unit testing? Has anyone done anything like this before? any examples in github?

I'm pretty sure I did a few years ago, just cant remember at all.


Solution

  • Setup the mock and pass that into the subject under test via constructor injection.

    public async Task MyTestMehod() {
    
        // Arrange
        Mock<IQuoteBank> mock = new Mock<IQuoteBank>();
        
        mock.Setup(_ =>  _.getQuote()).Returns("my consistent quote here")
        
        var subject = new QuoteFunction(mock.Object);
        
        //Act        
        IActionResult result = await subject.Run(Mock.Of<HttpRequest>(), Mock.Of<ILogger>());
        
        //Assert
        
        // ... assert my expected behavior
    }