For current capabilities, package layout, and common commands, see README.md. For architectural rationale (ALC isolation, FrameworkReference, GrpcWorker no-op, durable converter interception), see the "Architecture & Design Decisions" section in README.md. This file is limited to active blockers and known caveats.
- No active blockers for the current Worker SDK 2.x sample/test suites (including the latest Durable fake API support and CI-aligned test expectations).
FunctionsTestHostBuilder.ConfigureEnvironmentVariable(name, value)sets process-level environment variables, so tests that need different values for the same variable name should not run in parallel.[FromBody]only works in ASP.NET Core integration mode. In direct gRPC mode, the Worker SDK'sDefaultFromBodyConversionFeaturereads headers fromRpcHttp.NullableHeaders, which the framework's proto definition does not yet include. Workaround: usereq.ReadFromJsonAsync<T>()instead of[FromBody]in functions tested via direct gRPC mode.- The durable support package currently uses a framework-owned fake path (
ConfigureFakeDurableSupport(...)+FunctionsDurableClientProvider) instead of the real Durable runtime and execution engine. - Fake durable pageable query APIs (
GetAllInstancesAsync,GetAllEntitiesAsync) currently return a single in-memory page and ignore continuation tokens; they are intended for test scenarios, not backend-scale pagination fidelity. - When using
FunctionsApplicationBuilderwithConfigureFunctionsWebApplication(), callConfigureFunctionsWebApplication()before anyUseMiddleware<T>()calls. The SDK'sFunctionsHttpProxyingMiddlewaremust run first to populateFunctionContext.Items["HttpRequestContext"]; otherwise user middleware callingGetHttpRequestDataAsync()poisons the SDK's internal binding cache. The framework includes a cache-clearing middleware as a safety net, but correct ordering ensures the user middleware sees theHttpContextit expects. - Worker-side logging is suppressed by default. The worker host's minimum log level is set to
Warningto keep output clean. If your function code usesILoggerand you want to see those logs in test results, useConfigureWorkerLogging(logging => { logging.SetMinimumLevel(LogLevel.Information); logging.AddProvider(yourProvider); }). See the "Worker-side Logging" section inREADME.md. DurableClientBindingDefaultsmoved to the Durable package. If you previously referencedAzureFunctions.TestFramework.Core.DurableClientBindingDefaults, update theusingdirective toAzureFunctions.TestFramework.Durable.DurableClientBindingDefaults. This type was only intended for Durable-specific scenarios.[BlobInput]/[BlobTrigger]with SDK client types (BlobClient,BlockBlobClient, etc.) requireWithBlobServiceClient(blobServiceClient)on the builder. For[BlobInput]paths targeting client types, also callWithBlobInputClient("container/blob"). TheWithBlobInputContentextension is for content types only (string,byte[],Stream,BinaryData).[TableInput]withTableClientparameters is not supported byWithTableEntity/WithTableEntities. TheWithTableEntity/WithTableEntitiesbuilder extensions inject JSON for the binding, which covers POCO types andTableEntity/ITableEntity(single entity and collections).TableClientuses a different model-binding-data mechanism. ForTableClientparameters, override the Azure Tables SDK client in DI viaConfigureServices(services => services.AddSingleton<TableServiceClient>(fakeTableServiceClient)).[CosmosDBInput]with complex SDK types (e.g.CosmosClient,Container,DatabaseProxy) is not supported byWithCosmosDBInputDocuments. TheWithCosmosDBInputDocumentsbuilder extensions inject JSON for the binding, which covers POCO types andstring. Complex SDK client types use model-binding-data. For those parameters, override the Cosmos SDK client in DI viaConfigureServices(services => services.AddSingleton<CosmosClient>(fakeCosmosClient)).[SqlInput]with complex SDK types is not supported byWithSqlInputRows. TheWithSqlInputRowsbuilder extensions inject JSON for the binding, which covers POCO types andIEnumerable<T>. The lookup key is thecommandTextvalue declared in the[SqlInput]attribute (case-insensitive). When usingInvokeSqlAsync(string changesJson)directly,SqlChangeOperationenum values must be integers (0=Insert, 1=Update, 2=Delete) becauseSystem.Text.Jsonuses numeric enum serialization by default.[KustoInput]lookup is based ondatabase+ table name parsed fromKqlCommand.WithKustoInputRows(database, table, ...)matches the first table identifier in theKqlCommand(for example"InputTable | take 10"). Queries that begin with declarations or non-table expressions may not match this lookup strategy.[RedisInput]supports string-typed parameters only viaWithRedisInput. TheWithRedisInput(command, value)builder extension injects a string value keyed by the fullcommandstring declared in the[RedisInput]attribute (case-insensitive, e.g."GET mykey"). For JSON-typed injection useWithRedisInputJson(command, json). Redis trigger methods (InvokeRedisPubSubAsync,InvokeRedisListAsync,InvokeRedisStreamAsync) pass trigger values asstringbinding data; functions whose parameters are typed asstringreceive the raw value directly.SignalRMessageAction/SignalRGroupActioncannot be deserialized directly viaReadReturnValueAs<T>(). Both types have multiple parameterized constructors with no[JsonConstructor]attribute, soSystem.Text.Jsoncannot select one unambiguously. Read the[SignalROutput]return value asJsonElementand inspect properties viaGetProperty(...)instead.
The framework enforces a one function-app project per test project constraint. When multiple function-app projects compile to the same output directory, the last-built host.json overwrites the others. The Azure Functions SDK reads host.json from FUNCTIONS_APPLICATION_DIRECTORY at runtime, so the "winning" file determines settings like extensions.http.routePrefix for all test hosts sharing that output directory. Keep a 1:1 mapping between test projects and function-app projects to avoid this.