Class TestActorProvider
Mutable IActorProvider for integration and authorization testing. Stores the current actor in an AsyncLocal<T> so parallel tests using overlapping WithActor(Actor) scopes never interfere with each other.
public sealed class TestActorProvider : IActorProvider
- Inheritance
-
TestActorProvider
- Implements
- Inherited Members
- Extension Methods
Examples
var actorProvider = new TestActorProvider("admin", "Orders.Read", "Orders.Write");
// Temporarily switch to a restricted user
await using var scope = actorProvider.WithActor("user-1", "Orders.Read");
var result = await mediator.Send(new CreateOrderCommand());
result.Should().BeFailure(); // missing Orders.Write
// scope disposes → actor reverts to admin
Constructors
TestActorProvider(string, params string[])
Initializes a new TestActorProvider with an actor created from the specified user ID and permissions.
public TestActorProvider(string userId, params string[] permissions)
Parameters
userIdstringThe unique identifier of the actor.
permissionsstring[]The permissions granted to the actor.
TestActorProvider(Actor)
Initializes a new TestActorProvider with the specified Actor.
public TestActorProvider(Actor actor)
Parameters
actorActorThe initial (default) actor returned when no scope is active.
Exceptions
- ArgumentNullException
Thrown when
actoris null.
Methods
GetCurrentActorAsync(CancellationToken)
Returns the current authenticated actor for the request, or None when the request has no usable authenticated actor.
public Task<Maybe<Actor>> GetCurrentActorAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenToken to cancel the asynchronous operation.
Returns
- Task<Maybe<Actor>>
From<T>(T?) wrapping the resolved Actor when an authenticated identity is present and the framework can identify the actor.
None when the request has no usable authenticated actor — typically the request lacks credentials, the authentication middleware did not produce an authenticated identity, or the authenticated identity is missing the claim needed to identify the actor. The Trellis mediator authorization pipeline maps this to Error.AuthenticationRequired (HTTP 401) per RFC 9110 §15.5.2. "No authenticated actor" is client-error state, not an exception — model it via the return value, not by throwing.
Exceptions
- InvalidOperationException
Thrown only for genuine infrastructure or configuration failures — for example, the provider was invoked outside an HTTP request scope (missing
HttpContext), a user-supplied mapping delegate threw, or an option is misconfigured. The mediator pipeline does not catch this case; it surfaces as Error.Unexpected (HTTP 500), which is correct because these are bugs rather than authentication state. Do not throw for "missing actor" — return None instead.
WithActor(string, params string[])
Temporarily replaces the current actor with one created from the specified user ID and permissions. Returns a TestActorScope that restores the previous actor on dispose.
public TestActorScope WithActor(string userId, params string[] permissions)
Parameters
userIdstringThe unique identifier of the actor.
permissionsstring[]The permissions granted to the actor.
Returns
- TestActorScope
A disposable scope that restores the previous actor.
WithActor(Actor)
Temporarily replaces the current actor for the current async flow. Returns a TestActorScope that restores the previous actor on dispose.
public TestActorScope WithActor(Actor actor)
Parameters
actorActorThe actor to use for the duration of the scope.
Returns
- TestActorScope
A disposable scope that restores the previous actor.
Exceptions
- ArgumentNullException
Thrown when
actoris null.