Azure / Azure/azure-functions-dotnet-worker

Integration Testing isolated Functions

Open
#968 19 comments 16 reactions 1 assignee Claimed by @kshyju View on GitHub
Dominant language
C#
Stars
466
Forks
215
Avg merge
3d 10h
Merged PRs (30d)
7

Description

I've just migrated my functions from netcore3.1 V3 to net6.0 V4.
They are simple functions that use an Azure Storage Queue trigger.

Back in .netcore3.1 I was integration testing my functions (end to end) by creating a custom `IHost` like this:
```
this.host = new HostBuilder()
.ConfigureWebJobs((context, builder) => new Startup().Configure(new WebJobsBuilderContext
{
ApplicationRootPath = context.HostingEnvironment.ContentRootPath,
Configuration = context.Configuration,
EnvironmentName = context.HostingEnvironment.EnvironmentName
}, builder.AddAzureStorage(options => options.MaxDequeueCount = 1)))
.ConfigureServices((context, services) => { services.AddSingleton(); })
.Build();

this.host.Start();
```
and then I could write a simple test that dropped a message on an Azurite storage queue and see that the function picked it up and delivered it. (In my case it just calls a specific API in my backend).

The point is that these integration tests run the functions in the testing process (xUnit Runner), and I get the benefits of debugging in my tests. (No 3rd party hosts, CLI's or the like)

Now that I have migrated to V4 and .Net6.0, I am struggling to use the same basic test harness, which would look like something like this:
```
this.host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices((context, services) =>
{
services.AddSingleton();
})
.Build();

this.host.Start();
```
Except for the fact that, it seems impossible due to these constraints:
- `ConfigureFunctionsWorkerDefaults` sets up all the middleware, AND also configures GRPC support (`services.AddGrpc()`). But at runtime fails, because Grpc fails to initialise, missing a bunch of configurations.
- Even if I provide the necessary configuration (e.g. `Port`, `Host`, `WorkerId`, `RequestId` and `GrpcMaxMessageLength`) the code throws exceptions since the endpoint is not actually present. I have no idea what it does and why we need it.
- Even if I unregister the `FunctionRpcClient` and the `GrpcWorker` from the container (via `services.RemoveAll()`), it still fails at runtime since there is no registered `IWorker` in the container anymore that is required downstream by `WorkerHostedService`.
- I cannot implement my own `IWorker` implementation because `IWorker` is internal.
- I tried replacing your `WorkerHostedService` with my own class to remove the dependence on `IWorker`.
- Now, if I replace all the Grpc stuff and use my own `WorkerHostedService`, the functions never get triggered by the presence of items on the queues.
- I cannot just replace `ConfigureFunctionsWorkerDefaults()` with `ConfigureFunctionsWorker()` (as [suggested here](https://github.com/Azure/azure-functions-dotnet-worker/issues/808#issuecomment-1082399241)) since we are still missing an implementation of `IWorker` in the container, and I cannot put my own one in the container because that interface is `internal`.
- I tried removing the `WorkerHostedService` and replacing with my own, to remove the dependence on an `IWorker` and all that works at runtime, except now my functions are never triggered by messages arriving on the queue.

Like so:

```
this.host = new HostBuilder()
.ConfigureFunctionsWorker((_, _) => { }, _ => { })
.ConfigureServices((context, services) =>
{
services.RemoveAll();
services.AddSingleton();
services.AddSingleton();
})
.Build();

this.host.Start();
```
using my own `IHostedService`:
```
internal class WorkerHostedService : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
await Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
```

I don't really understand what is needed to be in place for my functions to be triggered by messages arriving on the queues.

Can you give me a clue as to what is missing?

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.