Azure / azure-functions-dotnet-extensions

Azure Functions .NET extensions
MIT License
75 stars 41 forks source link

Why is the context not available on IFunctionsHostBuilder, but on internal interface IFunctionsHostBuilderExt #68

Closed CasperWSchmidt closed 1 month ago

CasperWSchmidt commented 2 years ago

Hi there

I'm trying to do some testing to ensure that our functions will startup correctly, but instead of using Microsofts DI framework, we use SimpleInjector. To make sure that we can use services registered in both frameworks we use the approach described here. In my tests, I want to call the method Configure to get everything registered and then be able to access the instance of Container to check if relevant services are registered correctly. Our Azure Functions are humble objects that simply ask the mediator to handle the request, but this call requires the correct handlers to be able to be resolved from the container in order for the functions to run correctly.

I have tried to make stub classes for FunctionsHostBuilderContext and FunctionsHostBuilder, but even though i create an instance of WebJobsBuilderContext and set my configuration stub correctly, it is not returned to my startup code because GetContext() on IFunctionsHostBuilder is an extension method that checks if the context is an instance of the internal interface IFunctionsHostBuilderExt. If not, it returns a new default context.

This makes it really hard to test if the startup process registers everything correctly. Why is GetContext() not just a method on IFunctionsHostBuilder, and if not, why not expose IFunctionsHostBuilderExt to the public so that my own stub class can inherit from this interface as well :)

Any other ideas as to how I can test this are welcome.

My test classes looks like this:

private class StartupHelper : Startup
    {
        public Container GetContainer()
        {
            return Container;
        }
    }

    public class FunctionsHostBuilderStub : IFunctionsHostBuilder
    {
        public FunctionsHostBuilderContext Context { get; }
        public IServiceCollection Services { get; }

        public FunctionsHostBuilderStub(FunctionsHostBuilderContext context, IServiceCollection services)
        {
            Context = context;
            Services = services;
            Services.AddLogging();
        }
    }

    private class FunctionsHostBuilderContextStub : FunctionsHostBuilderContext
    {
        public FunctionsHostBuilderContextStub(WebJobsBuilderContext webJobsBuilderContext) : base(webJobsBuilderContext)
        {
        }
    }

The test I'm trying to run:

public void ShouldBeAbleToSetupDependencies()
{
    var startup = new StartupHelper();
    var services = new ServiceCollection();
    var webJobsBuilderContext = new WebJobsBuilderContext
    {
        Configuration = new ConfigurationStub()
    };
    var context = new FunctionsHostBuilderContextStub(webJobsBuilderContext);
    var functionHostBuilder = new FunctionsHostBuilderStub(context, services);
    startup.Configure(functionHostBuilder);
    var container = startup.GetContainer();

    Assert.NotNull(container.GetInstance<SomeHandler>());
    Assert.NotNull(container.GetInstance<SomeOtherHandler>());
}

Ideally I would just create in instance of FunctionsHostBuilder and provide the configuration, but that is not possible because the class is internal as well...

CasperWSchmidt commented 2 years ago

Still no answer to this? Is Azure Functions completely dead? @anthonychu

CasperWSchmidt commented 2 years ago

@fabiocav @brettsam @anthonychu Has Microsoft completely stopped developing this? Looking at closed issues the latest was closed January 2021 and none of the recently opened issues has been answered (including this one). It's not easy trusting Azure Functions in production when you get the feeling that MS does not prioritize it...

CasperWSchmidt commented 2 years ago

This is truly a bad customer experience. more than 4 months without any kind of response! I guess Azure Functions are truly dead and we are forced to move to AWS or GCP to be taken seriously :(

CasperWSchmidt commented 1 year ago

Still nothing? This is impresive!

ycherkes commented 1 year ago

@CasperWSchmidt Have you tried this workaround?

var startup = new StartupHelper();
var webJobsBuilderContext = new WebJobsBuilderContext
{
    Configuration = new ConfigurationStub()
};

using var host = new HostBuilder()
.ConfigureWebJobs(webJobsBuilder => startup.Configure(webJobsBuilderContext, webJobsBuilder))
.Build();

var container = startup.GetContainer();

Assert.NotNull(container.GetInstance<SomeHandler>());
Assert.NotNull(container.GetInstance<SomeOtherHandler>());

It's a slightly modified version of a code described in the article Integration Testing in Azure Functions with Dependency Injection by Saeb Amini

CasperWSchmidt commented 1 year ago

@ycherkes No - I will definitely try that when I get the time :)

mattchenderson commented 1 month ago

Apologies for lack of engagement here.

This item reflects a feature request, and we do not presently have plans to make changes to this component outside of what is necessary to support the in-process model through its remaining support window.