Skip to content

Commit 8cfba44

Browse files
committed
Added tests + cleanup
1 parent 6cda75e commit 8cfba44

File tree

9 files changed

+102
-58
lines changed

9 files changed

+102
-58
lines changed

Samples/AspNetCoreApp/Startup.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public void ConfigureServices(IServiceCollection services)
4949
// Swagger.
5050
services.AddSwaggerGen(c =>
5151
{
52-
c.SwaggerDoc("v1", new Info { Title = "AspNetCore Basic Registration Sample", Version = "v1" });
52+
c.SwaggerDoc("v1", new Info { Title = "AspNetCore Sample", Version = "v1" });
5353
c.IncludeXmlComments(AspNetCoreAppXmlDocPath);
5454
});
5555

@@ -70,9 +70,8 @@ public void ConfigureServices(IServiceCollection services)
7070
services.AddTransient<DeactivateProductCommandHandler>();
7171
services.AddTransient<ProductDomainEventsHandler>();
7272

73-
// Register message handler resolver to the container.
74-
// This is resolved by the MessageDelegator.
75-
services.AddSingleton<IMessageHandlerResolver>((serviceProvider) =>
73+
// Register message delegator to the container.
74+
services.AddSingleton<IMessageDelegator>((serviceProvider) =>
7675
{
7776
// Register command handlers to the message handler registration.
7877
// Commands can only have one handler so use SingleMessageHandlerRegistration.
@@ -83,15 +82,13 @@ public void ConfigureServices(IServiceCollection services)
8382
MultiMessageHandlerRegistration eventHandlerRegistration = RegisterEventHandlers(serviceProvider);
8483

8584
// Combine command handlers and event handlers.
86-
return new CompositeMessageHandlerResolver(new IMessageHandlerResolver[]
87-
{
85+
var resolver = CompositeMessageHandlerResolver.Compose(
8886
commandHandlerRegistration.BuildMessageHandlerResolver(),
8987
eventHandlerRegistration.BuildMessageHandlerResolver()
90-
});
91-
});
88+
);
9289

93-
// Message delegator.
94-
services.AddSingleton<IMessageDelegator, MessageDelegator>();
90+
return new MessageDelegator(resolver);
91+
});
9592
}
9693

9794
private static SingleMessageHandlerRegistration RegisterCommandHandlers(IServiceProvider serviceProvider)

Samples/ConsoleApp/Program.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ private static App Setup(string[] args)
5353
// Register console app use cases.
5454
container.RegisterCollection(typeof(IUseCase), typeof(IUseCase).Assembly);
5555

56-
// Message handler resolver.
57-
container.RegisterSingleton<IMessageHandlerResolver>(() =>
56+
// Message delegator.
57+
container.RegisterSingleton<IMessageDelegator>(() =>
5858
{
5959
// Register command handlers to the message handler registration.
6060
// Commands can only have one handler so use SingleMessageHandlerRegistration.
@@ -65,15 +65,13 @@ private static App Setup(string[] args)
6565
MultiMessageHandlerRegistration eventHandlerRegistration = RegisterEventHandlers(container);
6666

6767
// Combine command handlers and event handlers.
68-
return new CompositeMessageHandlerResolver(new IMessageHandlerResolver[]
69-
{
68+
var resolver = CompositeMessageHandlerResolver.Compose(
7069
commandHandlerRegistration.BuildMessageHandlerResolver(),
7170
eventHandlerRegistration.BuildMessageHandlerResolver()
72-
});
73-
});
71+
);
7472

75-
// Message delegator.
76-
container.RegisterSingleton<IMessageDelegator, MessageDelegator>();
73+
return new MessageDelegator(resolver);
74+
});
7775

7876
return new App(container);
7977
}

Samples/ConsoleApp/UseCases/DisplayAllProductsUseCase.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using System.Threading;
45
using System.Threading.Tasks;
56
using ReadSide.Products;
@@ -19,11 +20,10 @@ public DisplayAllProductsUseCase(IProductReadSideRepository productReadSideRepos
1920

2021
public override async Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
2122
{
22-
List<ProductReadModel> products = await _productReadSideRepository.GetAllProductsAsync(cancellationToken);
23-
products.ForEach(product =>
24-
{
23+
IReadOnlyCollection<ProductReadModel> products = await _productReadSideRepository.GetAllProductsAsync(cancellationToken);
24+
25+
foreach(ProductReadModel product in products)
2526
Console.WriteLine($"Product ID: {product.ProductId}, Product Name: {product.ProductName}, IsActive: {product.IsActive}");
26-
});
2727
}
2828
}
2929
}

Samples/Domain/Repositories/PublishingProductRepository.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,8 @@ public PublishingProductRepository(IProductRepository inner, IMessageDelegator m
2929

3030
// Do actual save.
3131
await _inner.SaveAsync(product, cancellationToken);
32-
3332
// Send each domain events to handlers.
34-
List<Task> publishDomainEventTasks = uncommittedDomainEvents.Select(e => _messageDelegator.SendAsync(e, cancellationToken)).ToList();
35-
36-
// Complete when all events have completed.
37-
await Task.WhenAll(publishDomainEventTasks);
33+
await _messageDelegator.SendAllAsync(uncommittedDomainEvents);
3834
}
3935
}
4036
}

Samples/ReadSide/Products/Repositories/IProductReadSideRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace ReadSide.Products.Repositories
66
{
77
public interface IProductReadSideRepository
88
{
9-
Task<List<ProductReadModel>> GetAllProductsAsync(CancellationToken cancellationToken = default(CancellationToken));
9+
Task<IReadOnlyCollection<ProductReadModel>> GetAllProductsAsync(CancellationToken cancellationToken = default(CancellationToken));
1010
Task<ProductReadModel> GetProductByIdAsync(int productId, CancellationToken cancellationToken = default(CancellationToken));
1111
Task<ProductReadModel> GetProductByNameAsync(string productName, CancellationToken cancellationToken = default(CancellationToken));
1212
Task AddProductAsync(ProductReadModel product, CancellationToken cancellationToken = default(CancellationToken));

Samples/ReadSide/Products/Repositories/InMemoryProductReadSideRepository.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ public class InMemoryProductReadSideRepository : IProductReadSideRepository
2626
return Task.CompletedTask;
2727
}
2828

29-
public Task<List<ProductReadModel>> GetAllProductsAsync(CancellationToken cancellationToken = default(CancellationToken))
29+
public Task<IReadOnlyCollection<ProductReadModel>> GetAllProductsAsync(CancellationToken cancellationToken = default(CancellationToken))
3030
{
31-
return Task.FromResult(_products.ToList());
31+
return Task.FromResult((IReadOnlyCollection<ProductReadModel>)_products.ToList());
3232
}
3333

3434
public Task<ProductReadModel> GetProductByIdAsync(int productId, CancellationToken cancellationToken = default(CancellationToken))

Tests/MessageDelegatorTests.cs

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Threading;
45
using System.Threading.Tasks;
56
using FluentAssertions;
67
using Xer.Delegator.Tests.Entities;
@@ -19,7 +20,7 @@ public class MessageDelegatorTests
1920
public class MessageDelegatorConstruction
2021
{
2122
[Fact]
22-
public void ShouldThrowWhenNullProvidedAsConstructorParameter()
23+
public void ShouldThrowWhenNullIsProvidedAsConstructorParameter()
2324
{
2425
// Given
2526
Action action = () =>
@@ -148,7 +149,7 @@ public async Task ShouldSendAllMessagesToASingleMessageHandler()
148149
actualMessageHandlerInvocationCount.Should().Be(expectedMessageHandlerInvocationCount);
149150
}
150151

151-
[Fact]
152+
[Fact]
152153
public void ShouldThrowWhenNullIsProvided()
153154
{
154155
// Given
@@ -164,9 +165,61 @@ public void ShouldThrowWhenNullIsProvided()
164165
// Then
165166
action.ShouldThrow<ArgumentNullException>();
166167
}
168+
169+
[Fact]
170+
public void ShouldThrowWhenCancelled()
171+
{
172+
// Given
173+
IMessageHandlerResolver resolver = CreateSingleMessageHandlerResolver(registration =>
174+
{
175+
registration.Register<TestMessage>((message, cancellationToken) =>
176+
{
177+
return Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);
178+
});
179+
});
180+
181+
MessageDelegator messageDelegator = CreateMessageDelegator(resolver);
182+
183+
Func<Task> action = async () =>
184+
{
185+
// Cancels after 1 second.
186+
using(var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1)))
187+
{
188+
// When
189+
await messageDelegator.SendAsync<TestMessage>(new TestMessage(), cts.Token);
190+
}
191+
};
192+
193+
// Then
194+
action.ShouldThrow<OperationCanceledException>();
195+
}
196+
197+
[Fact]
198+
public void ShouldPropagateExceptionFromHandler()
199+
{
200+
// Given
201+
IMessageHandlerResolver resolver = CreateSingleMessageHandlerResolver(registration =>
202+
{
203+
registration.Register<TestMessage>((message, cancellationToken) =>
204+
{
205+
return Task.FromException(new Exception("This exception is expected."));
206+
});
207+
});
208+
209+
MessageDelegator messageDelegator = CreateMessageDelegator(resolver);
210+
211+
Func<Task> action = () =>
212+
{
213+
// When
214+
return messageDelegator.SendAsync<TestMessage>(new TestMessage());
215+
};
216+
217+
// Then
218+
action.ShouldThrow<Exception>();
219+
}
167220
}
168221

169-
#endregion SyncAsync Method
222+
#endregion SendAsync Method
170223

171224
#region Common Methods
172225

Tests/Registration/MultiMessageHandlerRegistrationTests.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,43 +31,43 @@ public void ShouldAllowMultipleAsyncDelegatesPerMessageType()
3131
}
3232

3333
[Fact]
34-
public void ShouldNotAllowNullInRegisterAsyncDelegate()
34+
public void ShouldAllowMultipleSyncDelegatesPerMessageType()
3535
{
3636
// Given
3737
Action action = () =>
3838
{
3939
MultiMessageHandlerRegistration registration = CreateMultiHandlerRegistration();
40+
41+
// Stub
42+
Action<TestMessage> doNothingAction = (message) => {};
43+
4044
// When
41-
registration.Register<TestMessage>(null);
45+
registration.Register<TestMessage>(doNothingAction);
46+
registration.Register<TestMessage>(doNothingAction);
47+
registration.Register<TestMessage>(doNothingAction);
4248
};
4349

4450
// Then
45-
action.ShouldThrow<ArgumentNullException>("null is not allowed.");
51+
action.ShouldNotThrow<InvalidOperationException>("multiple message handler delegates per message type should be allowed.");
4652
}
4753

4854
[Fact]
49-
public void ShouldAllowMultipleSyncDelegatesPerMessageType()
55+
public void ShouldNotAllowNullWhenRegisteringAsyncHandler()
5056
{
5157
// Given
5258
Action action = () =>
5359
{
5460
MultiMessageHandlerRegistration registration = CreateMultiHandlerRegistration();
55-
56-
// Stub
57-
Action<TestMessage> doNothingAction = (message) => {};
58-
5961
// When
60-
registration.Register<TestMessage>(doNothingAction);
61-
registration.Register<TestMessage>(doNothingAction);
62-
registration.Register<TestMessage>(doNothingAction);
62+
registration.Register<TestMessage>(null);
6363
};
6464

6565
// Then
66-
action.ShouldNotThrow<InvalidOperationException>("multiple message handler delegates per message type should be allowed.");
66+
action.ShouldThrow<ArgumentNullException>("null is not allowed.");
6767
}
6868

6969
[Fact]
70-
public void ShouldNotAllowNullInRegisterSyncDelegate()
70+
public void ShouldNotAllowNullWhenRegisteringSyncHandler()
7171
{
7272
// Given
7373
Action action = () =>

Tests/Registration/SingleMessageHandlerRegistrationTests.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,42 @@ public void ShouldOnlyAllowOneAsyncDelegatePerMessageType()
3030
}
3131

3232
[Fact]
33-
public void ShouldNotAllowNullInRegisterAsyncDelegate()
33+
public void ShouldOnlyAllowOneSyncDelegatePerMessageType()
3434
{
3535
// Given
3636
Action action = () =>
3737
{
3838
SingleMessageHandlerRegistration registration = CreateSingleHandlerRegistration();
39+
40+
// Stub
41+
Action<TestMessage> doNothingAction = (message) => {};
42+
3943
// When
40-
registration.Register<TestMessage>(null);
44+
registration.Register<TestMessage>(doNothingAction);
45+
registration.Register<TestMessage>(doNothingAction);
4146
};
4247

4348
// Then
44-
action.ShouldThrow<ArgumentNullException>("null is not allowed.");
49+
action.ShouldThrow<InvalidOperationException>("only one message handler delegate per message type should be allowed.");
4550
}
4651

4752
[Fact]
48-
public void ShouldOnlyAllowOneSyncDelegatePerMessageType()
53+
public void ShouldNotAllowNullWhenRegisteringAsyncHandler()
4954
{
5055
// Given
5156
Action action = () =>
5257
{
5358
SingleMessageHandlerRegistration registration = CreateSingleHandlerRegistration();
54-
55-
// Stub
56-
Action<TestMessage> doNothingAction = (message) => {};
57-
5859
// When
59-
registration.Register<TestMessage>(doNothingAction);
60-
registration.Register<TestMessage>(doNothingAction);
60+
registration.Register<TestMessage>(null);
6161
};
6262

6363
// Then
64-
action.ShouldThrow<InvalidOperationException>("only one message handler delegate per message type should be allowed.");
64+
action.ShouldThrow<ArgumentNullException>("null is not allowed.");
6565
}
6666

6767
[Fact]
68-
public void ShouldNotAllowNullInRegisterSyncDelegate()
68+
public void ShouldNotAllowNullWhenRegisteringSyncHandler()
6969
{
7070
// Given
7171
Action action = () =>

0 commit comments

Comments
 (0)