Class TestDurableWorkflow
- Namespace
- XBullet.EasyTesting.AzureFunctions
- Assembly
- XBullet.EasyTesting.AzureFunctions.dll
Connects an in-memory Durable client to named orchestrators and activities through a borrowed function host.
public sealed class TestDurableWorkflow : ITestScenarioResource, IAsyncDisposable
- Inheritance
-
TestDurableWorkflow
- Implements
- Inherited Members
- Extension Methods
Remarks
Each function uses the host's middleware and a fresh DI scope. Payloads use direct assignment by default; WithSerialization enables SDK converter snapshots. Time is advanced on individual contexts. This helper does not implement replay, persistence, continuations, scheduled starts, or production lifecycle policies. WithRetries enables bounded retry simulation. Dispose this workflow before its host; register the workflow, rather than its client, as a scenario resource.
Constructors
TestDurableWorkflow(TestDurableTaskClient?, TimeSpan?)
Creates a workflow that can be registered in DI and as a scenario resource before attaching its host.
public TestDurableWorkflow(TestDurableTaskClient? client = null, TimeSpan? shutdownTimeout = null)
Parameters
clientTestDurableTaskClientAn optional caller-owned client registered in application DI. Its schedule, lookup, event, and wait handlers must be unset; this workflow wires them for its lifetime. Null creates an owned client.
shutdownTimeoutTimeSpan?A positive finite wall-clock cleanup limit, defaulting to five seconds. User code must honor cancellation.
Properties
Attempts
Gets immutable snapshots of activity and child attempts, including calls without retry options.
public IReadOnlyList<RecordedDurableTaskAttempt> Attempts { get; }
Property Value
- IReadOnlyList<RecordedDurableTaskAttempt>
An ordered snapshot containing original exceptions; diagnostics omit exception contents.
Client
Gets the client wired for scheduling, metadata, events, and start/completion waits.
public TestDurableTaskClient Client { get; }
Property Value
- TestDurableTaskClient
Use this client in starters or register it as DurableTaskClient in application DI. Do not replace its workflow handlers or reset it independently.
Methods
AddActivity<TFunction, TInput>(string, Func<TFunction, TInput, TestFunctionContext, Task>)
Registers an activity without a result.
public TestDurableWorkflow AddActivity<TFunction, TInput>(string name, Func<TFunction, TInput, TestFunctionContext, Task> invoke) where TFunction : notnull
Parameters
namestringThe non-empty, unique, case-sensitive task name.
invokeFunc<TFunction, TInput, TestFunctionContext, Task>The non-null callback borrowing the scoped function and worker context.
Returns
- TestDurableWorkflow
This workflow for chaining.
Type Parameters
TFunctionThe function class already registered in the borrowed host.
TInputThe assignable input type.
AddActivity<TFunction, TInput, TResult>(string, Func<TFunction, TInput, TestFunctionContext, Task<TResult>>)
Registers an activity delegate under a case-sensitive task name.
public TestDurableWorkflow AddActivity<TFunction, TInput, TResult>(string name, Func<TFunction, TInput, TestFunctionContext, Task<TResult>> invoke) where TFunction : notnull
Parameters
namestringThe non-empty task name. Duplicate registrations are rejected.
invokeFunc<TFunction, TInput, TestFunctionContext, Task<TResult>>The non-null callback receiving the scoped function, input, and worker context with its execution token.
Returns
- TestDurableWorkflow
This workflow for chaining. Every activity call gets a separate invocation scope.
Type Parameters
TFunctionThe function class already registered in the borrowed host.
TInputThe assignable activity input type, or deserialization target when serialization is enabled.
TResultThe activity result type.
AddOrchestrator<TFunction>(string, Func<TFunction, TestOrchestrationContext, TestFunctionContext, Task>)
Registers an orchestrator without a result.
public TestDurableWorkflow AddOrchestrator<TFunction>(string name, Func<TFunction, TestOrchestrationContext, TestFunctionContext, Task> invoke) where TFunction : notnull
Parameters
namestringThe non-empty, unique, case-sensitive task name.
invokeFunc<TFunction, TestOrchestrationContext, TestFunctionContext, Task>The non-null callback borrowing the scoped function and contexts.
Returns
- TestDurableWorkflow
This workflow for chaining.
Type Parameters
TFunctionThe function class already registered in the borrowed host.
AddOrchestrator<TFunction, TResult>(string, Func<TFunction, TestOrchestrationContext, TestFunctionContext, Task<TResult>>)
Registers an orchestrator delegate under a case-sensitive task name.
public TestDurableWorkflow AddOrchestrator<TFunction, TResult>(string name, Func<TFunction, TestOrchestrationContext, TestFunctionContext, Task<TResult>> invoke) where TFunction : notnull
Parameters
namestringThe non-empty task name. Duplicate registrations are rejected.
invokeFunc<TFunction, TestOrchestrationContext, TestFunctionContext, Task<TResult>>The non-null callback receiving the scoped function, orchestration context, and worker context with its execution token.
Returns
- TestDurableWorkflow
This workflow for chaining. Register before the first schedule or after reset.
Type Parameters
TFunctionThe function class already registered in the borrowed host.
TResultThe result returned by the orchestrator.
CaptureDiagnosticsAsync(CancellationToken)
Captures client operations and workflow summaries before scenario cleanup.
public ValueTask<object?> CaptureDiagnosticsAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenCancels before the snapshot is captured.
Returns
- ValueTask<object>
A serializable snapshot containing instance IDs, names, statuses, parent IDs, and call counts; payloads and failures are excluded.
DisposeAsync()
Cancels and drains executions before releasing workflow-owned cancellation resources.
public ValueTask DisposeAsync()
Returns
- ValueTask
A value task completing within the configured cleanup timeout. The host is never disposed by this workflow.
Remarks
On timeout, keep the host alive, release uncooperative work, and retry disposal. Client recordings remain available.
GetContext(string)
Gets the context of a scheduled root or child instance.
public TestOrchestrationContext GetContext(string instanceId)
Parameters
instanceIdstringThe non-empty case-sensitive instance ID.
Returns
- TestOrchestrationContext
The borrowed context for advancing time and inspecting calls. Do not replace its identity or dispatch configuration while it executes.
GetResultAsync<TResult>(string, CancellationToken)
Waits for one instance's result and propagates its original failure.
public Task<TResult> GetResultAsync<TResult>(string instanceId, CancellationToken cancellationToken = default)
Parameters
instanceIdstringThe non-empty case-sensitive root or child instance ID.
cancellationTokenCancellationTokenCancels this wait without canceling execution. Use a timeout or cancellation for workflows waiting on events or timers.
Returns
- Task<TResult>
The result after its invocation scope has closed.
Type Parameters
TResultThe assignable result type, or deserialization target when serialization is enabled; null requires a nullable type.
ResetAsync(CancellationToken)
Cancels and drains all executions, clears client recordings and instances, and retains registrations.
public ValueTask ResetAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenCancels cleanup waiting. Once cleanup begins, execution cancellation is not rolled back.
Returns
- ValueTask
A value task completing when invocation scopes close and state is reset.
Remarks
Cleanup is bounded by the constructor timeout. Failed cleanup retains instance diagnostics for inspection and retry. Concurrent cleanup is rejected.
UseHost(AzureFunctionTestHost)
Attaches the host used for every subsequent function invocation.
public TestDurableWorkflow UseHost(AzureFunctionTestHost host)
Parameters
hostAzureFunctionTestHostThe non-null caller-owned host containing the registered function classes. Attach exactly once, before scheduling.
Returns
- TestDurableWorkflow
This workflow for chaining. Dispose the workflow before the host.
WithRetries(int, Action<RecordedDurableTaskAttempt>?)
Enables bounded simulation of SDK retry policies and handlers for connected task calls.
public TestDurableWorkflow WithRetries(int maximumAttempts = 100, Action<RecordedDurableTaskAttempt>? retryScheduled = null)
Parameters
maximumAttemptsintThe positive upper bound per logical call, including the first attempt. Defaults to 100.
retryScheduledAction<RecordedDurableTaskAttempt>An optional observer called outside workflow locks after accepting a retry. It may advance the caller's manual clock. Observer failures stop the call.
Returns
- TestDurableWorkflow
This workflow for chaining. Configure before scheduling or after successful reset.
Remarks
Only calls with retry options retry. Policy delays use the calling context's manual clock; custom handlers control their own delay. Cancellation and sequence exhaustion are terminal. Reset preserves configuration and clears attempts. This does not emulate Durable replay or persisted retries.
WithSerialization(DataConverter?)
Enables serialization at connected workflow payload boundaries.
public TestDurableWorkflow WithSerialization(DataConverter? dataConverter = null)
Parameters
dataConverterDataConverterThe caller-owned, concurrently usable SDK converter; null selects the SDK JSON default.
Returns
- TestDurableWorkflow
This workflow for chaining. Configure before scheduling or after a successful reset.
Remarks
Snapshots root/child inputs, activity inputs/results, orchestration results, events, and custom status. Reads deserialize to the requested type. Recordings retain original references. Reset preserves configuration. This checks converter compatibility without emulating worker bindings, history, or replay.