Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Mocha/src/Mocha.Mediator/Mediator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ private ValueTask PublishCoreAsync(
{
var pipelines = runtime.GetNotificationPipelines(messageType);

if (pipelines.IsEmpty)
{
if (notification is not INotification)
{
throw ThrowHelper.NotANotification(messageType);
}

return default;
}

if (pipelines.Length == 1)
{
return PublishSingle(pipelines[0], notification, messageType, cancellationToken);
Expand Down
5 changes: 3 additions & 2 deletions src/Mocha/src/Mocha.Mediator/MediatorRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ public void ReturnContext(MediatorContext context)
}

/// <summary>
/// Gets the compiled notification pipeline delegates for the specified notification type.
/// Gets the compiled notification pipeline delegates for the specified notification type,
/// or an empty array if no handler is registered for it.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ImmutableArray<MediatorDelegate> GetNotificationPipelines(Type notificationType)
Expand All @@ -108,6 +109,6 @@ public ImmutableArray<MediatorDelegate> GetNotificationPipelines(Type notificati
return pipelines;
}

throw ThrowHelper.MissingNotificationPipeline(notificationType);
return [];
}
}
9 changes: 5 additions & 4 deletions src/Mocha/src/Mocha.Mediator/ThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ public static Exception MissingPipeline(Type messageType)
=> new InvalidOperationException(
$"No pipeline registered for message type {messageType}");

public static Exception MissingNotificationPipeline(Type notificationType)
=> new InvalidOperationException(
$"No notification pipeline registered for message type {notificationType}. "
+ "If this is a command or query, use SendAsync or QueryAsync instead.");
public static Exception NotANotification(Type type)
=> new ArgumentException(
$"Type '{type}' does not implement {nameof(INotification)}. "
+ "If this is a command or query, use SendAsync or QueryAsync instead.",
"notification");

public static Exception BeforeAndAfterConflict()
=> new ArgumentException(
Expand Down
56 changes: 53 additions & 3 deletions src/Mocha/test/Mocha.Mediator.Tests/MediatorDispatchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,59 @@ await Assert.ThrowsAsync<InvalidOperationException>(
() => mediator.SendAsync(new DispatchCommand("missing"), TestContext.Current.CancellationToken).AsTask());
await Assert.ThrowsAsync<InvalidOperationException>(
() => mediator.QueryAsync(new DispatchQuery(1), TestContext.Current.CancellationToken).AsTask());
await Assert.ThrowsAsync<InvalidOperationException>(
() => mediator.PublishAsync(new DispatchNotification("missing"), TestContext.Current.CancellationToken)
.AsTask());
}

[Fact]
public async Task PublishAsync_Should_Complete_When_NoNotificationHandlerRegistered()
{
// arrange
var sp = DispatchTestHelper.BuildProvider((_, _) => { });
using var scope = sp.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();

// act
var task = mediator.PublishAsync(new DispatchNotification("unhandled"), TestContext.Current.CancellationToken);

// assert
Assert.True(task.IsCompletedSuccessfully);
await task;
}

[Fact]
public async Task PublishAsync_Should_Complete_When_UntypedNotificationHasNoHandler()
{
// arrange
var sp = DispatchTestHelper.BuildProvider((_, _) => { });
using var scope = sp.CreateScope();
var publisher = scope.ServiceProvider.GetRequiredService<IPublisher>();

// act
var task = publisher.PublishAsync(
(object)new DispatchNotification("unhandled"),
TestContext.Current.CancellationToken);

// assert
Assert.True(task.IsCompletedSuccessfully);
await task;
}

[Fact]
public async Task PublishAsync_Should_ThrowArgumentException_When_ObjectIsNotANotification()
{
// arrange
var sp = DispatchTestHelper.BuildProvider((_, _) => { });
using var scope = sp.CreateScope();
var publisher = scope.ServiceProvider.GetRequiredService<IPublisher>();

// act
var exception = await Assert.ThrowsAsync<ArgumentException>(
() => publisher.PublishAsync(new DispatchVoidCommand("x"), TestContext.Current.CancellationToken).AsTask());

// assert
Assert.Equal(
"Type 'Mocha.Mediator.Tests.DispatchVoidCommand' does not implement INotification. "
+ "If this is a command or query, use SendAsync or QueryAsync instead. (Parameter 'notification')",
exception.Message);
}

[Fact]
Expand Down
Loading