diff --git a/src/Compat/IsExternalInit.cs b/src/Compat/IsExternalInit.cs
deleted file mode 100644
index bf44d73..0000000
--- a/src/Compat/IsExternalInit.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-// Init accessors compile against this marker type; netstandard2.0 and net462 do not ship it.
-namespace System.Runtime.CompilerServices;
-
-internal static class IsExternalInit
-{ }
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 58b969c..730951f 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -36,8 +36,8 @@
-
-
+
+
diff --git a/src/RequestFlow.Cqrs/CqrsDispatcher.cs b/src/RequestFlow.Cqrs/CqrsDispatcher.cs
index 7ae9b30..83c24b9 100644
--- a/src/RequestFlow.Cqrs/CqrsDispatcher.cs
+++ b/src/RequestFlow.Cqrs/CqrsDispatcher.cs
@@ -14,8 +14,7 @@ internal sealed class CqrsDispatcher(IRequestDispatcher dispatcher) : ICommandDi
///
public Task SendAsync(ICommand command, CancellationToken cancellationToken = default)
{
- if (command is null)
- throw new ArgumentNullException(nameof(command));
+ ThrowHelper.ThrowIfNull(command);
return _dispatcher.SendAsync(command, cancellationToken);
}
@@ -23,8 +22,7 @@ public Task SendAsync(ICommand command, Cancell
///
public Task SendAsync(ICommand command, CancellationToken cancellationToken = default)
{
- if (command is null)
- throw new ArgumentNullException(nameof(command));
+ ThrowHelper.ThrowIfNull(command);
return _dispatcher.SendAsync(command, cancellationToken);
}
@@ -32,8 +30,7 @@ public Task SendAsync(ICommand command, CancellationToken cancellationToken = de
///
public Task SendAsync(IQuery query, CancellationToken cancellationToken = default)
{
- if (query is null)
- throw new ArgumentNullException(nameof(query));
+ ThrowHelper.ThrowIfNull(query);
return _dispatcher.SendAsync(query, cancellationToken);
}
diff --git a/src/RequestFlow.Cqrs/CqrsStreamDispatcher.cs b/src/RequestFlow.Cqrs/CqrsStreamDispatcher.cs
index 3734a0e..295aa6f 100644
--- a/src/RequestFlow.Cqrs/CqrsStreamDispatcher.cs
+++ b/src/RequestFlow.Cqrs/CqrsStreamDispatcher.cs
@@ -14,8 +14,7 @@ internal sealed class CqrsStreamDispatcher(IStreamDispatcher dispatcher) : IStre
///
public IAsyncEnumerable Stream(IStreamQuery query, CancellationToken cancellationToken = default)
{
- if (query is null)
- throw new ArgumentNullException(nameof(query));
+ ThrowHelper.ThrowIfNull(query);
return _dispatcher.Stream(query, cancellationToken);
}
diff --git a/src/RequestFlow.Cqrs/CqrsValueDispatcher.cs b/src/RequestFlow.Cqrs/CqrsValueDispatcher.cs
index 1979590..5fa3c34 100644
--- a/src/RequestFlow.Cqrs/CqrsValueDispatcher.cs
+++ b/src/RequestFlow.Cqrs/CqrsValueDispatcher.cs
@@ -15,8 +15,7 @@ public ValueTask SendAsync(
IValueCommand command,
CancellationToken cancellationToken = default)
{
- if (command is null)
- throw new ArgumentNullException(nameof(command));
+ ThrowHelper.ThrowIfNull(command);
return _dispatcher.SendAsync(command, cancellationToken);
}
@@ -26,8 +25,7 @@ public ValueTask SendAsync(
IValueCommand command,
CancellationToken cancellationToken = default)
{
- if (command is null)
- throw new ArgumentNullException(nameof(command));
+ ThrowHelper.ThrowIfNull(command);
return _dispatcher.SendAsync(command, cancellationToken);
}
@@ -37,8 +35,7 @@ public ValueTask SendAsync(
IValueQuery query,
CancellationToken cancellationToken = default)
{
- if (query is null)
- throw new ArgumentNullException(nameof(query));
+ ThrowHelper.ThrowIfNull(query);
return _dispatcher.SendAsync(query, cancellationToken);
}
diff --git a/src/RequestFlow.Cqrs/ThrowHelper.cs b/src/RequestFlow.Cqrs/ThrowHelper.cs
new file mode 100644
index 0000000..8fbf3d1
--- /dev/null
+++ b/src/RequestFlow.Cqrs/ThrowHelper.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace RequestFlow.Cqrs;
+
+internal static class ThrowHelper
+{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void ThrowIfNull(
+ [NotNull] object? argument,
+ [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ if (argument is null)
+ ArgumentNull(paramName);
+ }
+
+ [DoesNotReturn]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ArgumentNull(string? paramName) => throw new ArgumentNullException(paramName);
+}
diff --git a/src/RequestFlow/Dispatch/DispatchMap.cs b/src/RequestFlow/Dispatch/DispatchMap.cs
index 5a0bb93..dff2bd5 100644
--- a/src/RequestFlow/Dispatch/DispatchMap.cs
+++ b/src/RequestFlow/Dispatch/DispatchMap.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
#if NET8_0_OR_GREATER
using System.Collections.Frozen;
@@ -16,6 +17,6 @@ internal sealed class DispatchMap(Dictionary plans)
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryGetPlanFor(Type requestType, out RequestPlanBase? plan)
+ public bool TryGetPlanFor(Type requestType, [NotNullWhen(true)] out RequestPlanBase? plan)
=> _plans.TryGetValue(requestType, out plan);
}
diff --git a/src/RequestFlow/Dispatch/NullTaskGuard.cs b/src/RequestFlow/Dispatch/NullTaskGuard.cs
index 685c8c6..0a2a649 100644
--- a/src/RequestFlow/Dispatch/NullTaskGuard.cs
+++ b/src/RequestFlow/Dispatch/NullTaskGuard.cs
@@ -8,17 +8,17 @@ internal static class NullTaskGuard
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task FromHandler(Task task, Type requestType)
- => task ?? throw new HandlerNullTaskException(requestType);
+ => task ?? ThrowHelper.HandlerNullTask>(requestType);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task FromStage(Task task, Type stageType)
- => task ?? throw new StageNullTaskException(stageType);
+ => task ?? ThrowHelper.StageNullTask>(stageType);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task FromEventHandler(Task task, Type eventType, Type handlerType)
- => task ?? throw new EventHandlerNullTaskException(eventType, handlerType);
+ => task ?? ThrowHelper.EventHandlerNullTask(eventType, handlerType);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task FromStrategy(Task task, Type strategyType)
- => task ?? throw new EventStrategyNullTaskException(strategyType);
+ => task ?? ThrowHelper.EventStrategyNullTask(strategyType);
}
diff --git a/src/RequestFlow/Dispatch/RequestDispatcher.cs b/src/RequestFlow/Dispatch/RequestDispatcher.cs
index d7eb99d..97f1211 100644
--- a/src/RequestFlow/Dispatch/RequestDispatcher.cs
+++ b/src/RequestFlow/Dispatch/RequestDispatcher.cs
@@ -12,16 +12,16 @@ internal sealed class RequestDispatcher(DispatchMap map, IServiceProvider servic
///
public Task SendAsync(IRequest request, CancellationToken cancellationToken = default)
{
- if (request is null)
- throw new ArgumentNullException(nameof(request));
+ ThrowHelper.ThrowIfNull(request);
Type requestType = request.GetType();
if (!_map.TryGetPlanFor(requestType, out RequestPlanBase? plan))
- throw new HandlerNotFoundException(requestType);
+ return ThrowHelper.HandlerNotFound>(requestType);
if (plan is not RequestPlan typedPlan)
- throw new ResponseTypeMismatchException(requestType, expected: plan!.ResponseType, actual: typeof(TResponse));
+ return ThrowHelper.ResponseTypeMismatch>(
+ requestType, expected: plan.ResponseType, actual: typeof(TResponse));
return typedPlan.ExecuteAsync(request, _services, cancellationToken);
}
@@ -29,8 +29,7 @@ public Task SendAsync(IRequest request, Cancell
///
public Task SendAsync(IRequest request, CancellationToken cancellationToken = default)
{
- if (request is null)
- throw new ArgumentNullException(nameof(request));
+ ThrowHelper.ThrowIfNull(request);
return SendAsync(request, cancellationToken);
}
diff --git a/src/RequestFlow/Dispatch/Streaming/NullStreamGuard.cs b/src/RequestFlow/Dispatch/Streaming/NullStreamGuard.cs
index c6bb134..5b4c8a8 100644
--- a/src/RequestFlow/Dispatch/Streaming/NullStreamGuard.cs
+++ b/src/RequestFlow/Dispatch/Streaming/NullStreamGuard.cs
@@ -8,9 +8,9 @@ internal static class NullStreamGuard
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IAsyncEnumerable FromHandler(IAsyncEnumerable stream, Type requestType)
- => stream ?? throw new HandlerNullStreamException(requestType);
+ => stream ?? ThrowHelper.HandlerNullStream>(requestType);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IAsyncEnumerable FromStage(IAsyncEnumerable stream, Type stageType)
- => stream ?? throw new StageNullStreamException(stageType);
+ => stream ?? ThrowHelper.StageNullStream>(stageType);
}
diff --git a/src/RequestFlow/Dispatch/Streaming/StreamDispatcher.cs b/src/RequestFlow/Dispatch/Streaming/StreamDispatcher.cs
index 3a68643..4726ed1 100644
--- a/src/RequestFlow/Dispatch/Streaming/StreamDispatcher.cs
+++ b/src/RequestFlow/Dispatch/Streaming/StreamDispatcher.cs
@@ -19,18 +19,32 @@ internal sealed class StreamDispatcher(DispatchMap map, IServiceProvider service
public IAsyncEnumerable Stream(
IStreamRequest request, CancellationToken cancellationToken = default)
{
- if (request is null)
- throw new ArgumentNullException(nameof(request));
+ ThrowHelper.ThrowIfNull(request);
Type requestType = request.GetType();
if (!_map.TryGetPlanFor(requestType, out RequestPlanBase? plan))
- throw new HandlerNotFoundException(requestType);
+ return ThrowHelper.HandlerNotFound>(requestType);
if (plan is not StreamPlan streamPlan)
- throw new ResponseTypeMismatchException(requestType, expected: plan!.ResponseType, actual: typeof(TItem));
+ return ThrowHelper.ResponseTypeMismatch>(
+ requestType, expected: plan.ResponseType, actual: typeof(TItem));
- return Walk(streamPlan, request, _services, cancellationToken);
+ return cancellationToken.CanBeCanceled
+ ? Walk(streamPlan, request, _services, cancellationToken)
+ : WalkWithoutDispatchToken(streamPlan, request, _services);
+ }
+
+ private static async IAsyncEnumerable WalkWithoutDispatchToken(
+ StreamPlan plan,
+ object request,
+ IServiceProvider services,
+ [EnumeratorCancellation] CancellationToken iterationToken = default)
+ {
+ await foreach (TItem item in plan.Execute(request, services, iterationToken).ConfigureAwait(false))
+ {
+ yield return item;
+ }
}
// The dispatch token arrives as a parameter and the iteration token through the attribute, so
diff --git a/src/RequestFlow/Dispatch/ThrowHelper.cs b/src/RequestFlow/Dispatch/ThrowHelper.cs
new file mode 100644
index 0000000..cf02d9e
--- /dev/null
+++ b/src/RequestFlow/Dispatch/ThrowHelper.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace RequestFlow;
+
+internal static class ThrowHelper
+{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void ThrowIfNull(
+ [NotNull] object? argument,
+ [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ if (argument is null)
+ ArgumentNull(paramName);
+ }
+
+ [DoesNotReturn]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ArgumentNull(string? paramName) => throw new ArgumentNullException(paramName);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult HandlerNotFound(Type requestType)
+ => throw new HandlerNotFoundException(requestType);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult ResponseTypeMismatch(Type requestType, Type expected, Type actual)
+ => throw new ResponseTypeMismatchException(requestType, expected, actual);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult EventNotRegistered(Type eventType)
+ => throw new EventNotRegisteredException(eventType);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult HandlerNullTask(Type requestType)
+ => throw new HandlerNullTaskException(requestType);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult StageNullTask(Type stageType)
+ => throw new StageNullTaskException(stageType);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult EventHandlerNullTask(Type eventType, Type handlerType)
+ => throw new EventHandlerNullTaskException(eventType, handlerType);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult EventStrategyNullTask(Type strategyType)
+ => throw new EventStrategyNullTaskException(strategyType);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult HandlerNullStream(Type requestType)
+ => throw new HandlerNullStreamException(requestType);
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static TResult StageNullStream(Type stageType)
+ => throw new StageNullStreamException(stageType);
+}
diff --git a/src/RequestFlow/Dispatch/ValueTask/ValueRequestDispatcher.cs b/src/RequestFlow/Dispatch/ValueTask/ValueRequestDispatcher.cs
index 9f4fe54..fa8cdb9 100644
--- a/src/RequestFlow/Dispatch/ValueTask/ValueRequestDispatcher.cs
+++ b/src/RequestFlow/Dispatch/ValueTask/ValueRequestDispatcher.cs
@@ -15,18 +15,17 @@ public ValueTask SendAsync(
IValueRequest request,
CancellationToken cancellationToken = default)
{
- if (request is null)
- throw new ArgumentNullException(nameof(request));
+ ThrowHelper.ThrowIfNull(request);
Type requestType = request.GetType();
if (!_map.TryGetPlanFor(requestType, out RequestPlanBase? plan))
- throw new HandlerNotFoundException(requestType);
+ return ThrowHelper.HandlerNotFound>(requestType);
if (plan is not ValueRequestPlan typedPlan)
- throw new ResponseTypeMismatchException(
+ return ThrowHelper.ResponseTypeMismatch>(
requestType,
- expected: plan!.ResponseType,
+ expected: plan.ResponseType,
actual: typeof(TResponse));
return typedPlan.ExecuteAsync(request, _services, cancellationToken);
@@ -37,13 +36,12 @@ public ValueTask SendAsync(
IValueRequest request,
CancellationToken cancellationToken = default)
{
- if (request is null)
- throw new ArgumentNullException(nameof(request));
+ ThrowHelper.ThrowIfNull(request);
Type requestType = request.GetType();
if (!_map.TryGetPlanFor(requestType, out RequestPlanBase? plan))
- throw new HandlerNotFoundException(requestType);
+ return ThrowHelper.HandlerNotFound(requestType);
if (plan is ValueVoidRequestPlan voidPlan)
return voidPlan.ExecuteVoidAsync(request, _services, cancellationToken);
@@ -52,9 +50,9 @@ public ValueTask SendAsync(
return ValueNoResultBridge.Discard(
typedPlan.ExecuteAsync(request, _services, cancellationToken));
- throw new ResponseTypeMismatchException(
+ return ThrowHelper.ResponseTypeMismatch(
requestType,
- expected: plan!.ResponseType,
+ expected: plan.ResponseType,
actual: typeof(NoResult));
}
}
diff --git a/src/RequestFlow/Events/EventMap.cs b/src/RequestFlow/Events/EventMap.cs
index bf4c6f4..21a5a74 100644
--- a/src/RequestFlow/Events/EventMap.cs
+++ b/src/RequestFlow/Events/EventMap.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
#if NET8_0_OR_GREATER
using System.Collections.Frozen;
@@ -16,6 +17,6 @@ internal sealed class EventMap(Dictionary plans)
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool TryGetPlanFor(Type eventType, out EventPlan? plan)
+ public bool TryGetPlanFor(Type eventType, [NotNullWhen(true)] out EventPlan? plan)
=> _plans.TryGetValue(eventType, out plan);
}
diff --git a/src/RequestFlow/Events/EventPlanFactory.cs b/src/RequestFlow/Events/EventPlanFactory.cs
index ebd5e34..b4be81f 100644
--- a/src/RequestFlow/Events/EventPlanFactory.cs
+++ b/src/RequestFlow/Events/EventPlanFactory.cs
@@ -43,7 +43,9 @@ private static EventPlan CreatePlan(
if (strategyType == typeof(SequentialPublishStrategy))
return new SequentialEventPlan(@event, entries);
if (strategyType == typeof(ParallelPublishStrategy))
- return new ParallelEventPlan(@event, entries);
+ return entries.Length == 1
+ ? new SequentialEventPlan(@event, entries)
+ : new ParallelEventPlan(@event, entries);
if (strategyType == typeof(FailFastPublishStrategy))
return new SequentialEventPlan(@event, entries, stopOnFirstFailure: true);
diff --git a/src/RequestFlow/Events/EventPublisher.cs b/src/RequestFlow/Events/EventPublisher.cs
index d345122..718e72a 100644
--- a/src/RequestFlow/Events/EventPublisher.cs
+++ b/src/RequestFlow/Events/EventPublisher.cs
@@ -11,13 +11,12 @@ internal sealed class EventPublisher(EventMap map, IServiceProvider services) :
public Task PublishAsync(IEvent @event, CancellationToken cancellationToken = default)
{
- if (@event is null)
- throw new ArgumentNullException(nameof(@event));
+ ThrowHelper.ThrowIfNull(@event, nameof(@event));
Type eventType = @event.GetType();
if (!_map.TryGetPlanFor(eventType, out EventPlan? plan))
- throw new EventNotRegisteredException(eventType);
+ return ThrowHelper.EventNotRegistered(eventType);
- return plan!.ExecuteAsync(@event, _services, cancellationToken);
+ return plan.ExecuteAsync(@event, _services, cancellationToken);
}
}
diff --git a/tests/Compat/IsExternalInit.cs b/tests/Compat/IsExternalInit.cs
deleted file mode 100644
index df3e4e8..0000000
--- a/tests/Compat/IsExternalInit.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-// Records compile to init accessors, and the compiler wants this marker type; .NET Framework does not ship it.
-namespace System.Runtime.CompilerServices;
-
-internal static class IsExternalInit
-{ }
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index bba9cd3..bbbcf1b 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -32,8 +32,8 @@
-
-
+
+
diff --git a/tests/RequestFlow.Cqrs.Tests.Unit/CqrsDispatcherTests.cs b/tests/RequestFlow.Cqrs.Tests.Unit/CqrsDispatcherTests.cs
index df59447..aa23cf3 100644
--- a/tests/RequestFlow.Cqrs.Tests.Unit/CqrsDispatcherTests.cs
+++ b/tests/RequestFlow.Cqrs.Tests.Unit/CqrsDispatcherTests.cs
@@ -52,24 +52,30 @@ public async Task Given_Query_When_Sending_Query_Then_Forwards_Query_And_Token_A
}
[Fact]
- public async Task Given_Null_Typed_Command_When_Sending_Command_Then_Throws_Argument_Null_Exception()
+ public void Given_Null_Typed_Command_When_Sending_Command_Then_Throws_Argument_Null_Exception()
{
- await Should.ThrowAsync(
- () => _sut.SendAsync((ICommand)null!));
+ var exception = Should.Throw(
+ () => { _sut.SendAsync((ICommand)null!); });
+
+ exception.ParamName.ShouldBe("command");
}
[Fact]
- public async Task Given_Null_Void_Command_When_Sending_Command_Then_Throws_Argument_Null_Exception()
+ public void Given_Null_Void_Command_When_Sending_Command_Then_Throws_Argument_Null_Exception()
{
- await Should.ThrowAsync(
- () => _sut.SendAsync((ICommand)null!));
+ var exception = Should.Throw(
+ () => { _sut.SendAsync((ICommand)null!); });
+
+ exception.ParamName.ShouldBe("command");
}
[Fact]
- public async Task Given_Null_Query_When_Sending_Query_Then_Throws_Argument_Null_Exception()
+ public void Given_Null_Query_When_Sending_Query_Then_Throws_Argument_Null_Exception()
{
- await Should.ThrowAsync(
- () => _sut.SendAsync((IQuery)null!));
+ var exception = Should.Throw(
+ () => { _sut.SendAsync((IQuery)null!); });
+
+ exception.ParamName.ShouldBe("query");
}
[Fact]
diff --git a/tests/RequestFlow.Cqrs.Tests.Unit/CqrsValueDispatcherTests.cs b/tests/RequestFlow.Cqrs.Tests.Unit/CqrsValueDispatcherTests.cs
index fdda492..0f6cebc 100644
--- a/tests/RequestFlow.Cqrs.Tests.Unit/CqrsValueDispatcherTests.cs
+++ b/tests/RequestFlow.Cqrs.Tests.Unit/CqrsValueDispatcherTests.cs
@@ -57,24 +57,30 @@ public async Task Given_A_Value_Query_When_Sending_Then_Forwards_It_And_The_Toke
}
[Fact]
- public async Task Given_A_Null_Value_Command_When_Sending_Then_Throws_Argument_Null_Exception()
+ public void Given_A_Null_Value_Command_When_Sending_Then_Throws_Argument_Null_Exception()
{
- await Should.ThrowAsync(
- async () => await _sut.SendAsync((IValueCommand)null!));
+ var exception = Should.Throw(
+ () => { _sut.SendAsync((IValueCommand)null!); });
+
+ exception.ParamName.ShouldBe("command");
}
[Fact]
- public async Task Given_A_Null_Void_Value_Command_When_Sending_Then_Throws_Argument_Null_Exception()
+ public void Given_A_Null_Void_Value_Command_When_Sending_Then_Throws_Argument_Null_Exception()
{
- await Should.ThrowAsync(
- async () => await _sut.SendAsync((IValueCommand)null!));
+ var exception = Should.Throw(
+ () => { _sut.SendAsync((IValueCommand)null!); });
+
+ exception.ParamName.ShouldBe("command");
}
[Fact]
- public async Task Given_A_Null_Value_Query_When_Sending_Then_Throws_Argument_Null_Exception()
+ public void Given_A_Null_Value_Query_When_Sending_Then_Throws_Argument_Null_Exception()
{
- await Should.ThrowAsync(
- async () => await _sut.SendAsync((IValueQuery)null!));
+ var exception = Should.Throw(
+ () => { _sut.SendAsync((IValueQuery)null!); });
+
+ exception.ParamName.ShouldBe("query");
}
[Fact]
diff --git a/tests/RequestFlow.Tests.Unit/Dispatch/RequestDispatcherTests.cs b/tests/RequestFlow.Tests.Unit/Dispatch/RequestDispatcherTests.cs
index 641fb0f..709f5d8 100644
--- a/tests/RequestFlow.Tests.Unit/Dispatch/RequestDispatcherTests.cs
+++ b/tests/RequestFlow.Tests.Unit/Dispatch/RequestDispatcherTests.cs
@@ -25,10 +25,10 @@ public async Task Given_Registered_Handler_When_Sending_Request_Then_Returns_Han
}
[Fact]
- public async Task Given_Unknown_Request_Type_When_Sending_Request_Then_Throws_Handler_Not_Found_Exception()
+ public void Given_Unknown_Request_Type_When_Sending_Request_Then_Throws_Handler_Not_Found_Exception()
{
- var exception = await Should.ThrowAsync(
- () => _sut.SendAsync(new Unknown()));
+ var exception = Should.Throw(
+ () => { _sut.SendAsync(new Unknown()); });
exception.RequestType.ShouldBe(typeof(Unknown));
}
@@ -55,10 +55,10 @@ public async Task Given_Synchronously_Completing_Void_Handler_When_Sending_Reque
}
[Fact]
- public async Task Given_Covariant_Response_Type_When_Sending_Request_Then_Throws_Response_Type_Mismatch_Exception()
+ public void Given_Covariant_Response_Type_When_Sending_Request_Then_Throws_Response_Type_Mismatch_Exception()
{
- var exception = await Should.ThrowAsync(
- () => _sut.SendAsync