Skip to content

Commit a83aa63

Browse files
authored
Merge pull request #1005 from Caliburn-Micro/publish_ui_tests
Add unit tests for EventAggregator thread behavior
2 parents 1b3142e + d7eb668 commit a83aa63

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using Moq;
5+
using Xunit;
6+
namespace Caliburn.Micro.Core.Tests
7+
{
8+
public class EventAggregatorExtensionsTests
9+
{
10+
const int NumberOfMockTargets = 20;
11+
[Fact]
12+
public void SubscribeOnUIThread_CallsSubscribeWithUIThreadMarshaller()
13+
{
14+
var mockAggregator = new Mock<IEventAggregator>();
15+
var subscriber = new object();
16+
17+
Func<Func<Task>, Task> capturedMarshaller = null;
18+
mockAggregator.Setup(x => x.Subscribe(subscriber, It.IsAny<Func<Func<Task>, Task>>()))
19+
.Callback<object, Func<Func<Task>, Task>>((_, m) => capturedMarshaller = m);
20+
21+
mockAggregator.Object.SubscribeOnUIThread(subscriber);
22+
23+
Assert.NotNull(capturedMarshaller);
24+
// UI thread marshaler returns a Task
25+
var taskSource = new TaskCompletionSource<bool>();
26+
var task = capturedMarshaller(() => { taskSource.SetResult(true); return taskSource.Task; });
27+
Assert.IsAssignableFrom<Task>(task);
28+
}
29+
30+
[Fact]
31+
public async Task PublishOnCurrentThreadAsync_CallsPublishAsyncWithDirectMarshaller()
32+
{
33+
var eventAggregator = new EventAggregator();
34+
string message = "Test";
35+
using (var tokenSource = new CancellationTokenSource())
36+
{
37+
var cancellationToken = tokenSource.Token;
38+
var mockTarget1 = new Mock<IHandle<string>>();
39+
var mockTarget2 = new Mock<IHandle<string>>();
40+
eventAggregator.SubscribeOnPublishedThread(mockTarget1.Object);
41+
eventAggregator.SubscribeOnPublishedThread(mockTarget2.Object);
42+
await eventAggregator.PublishOnCurrentThreadAsync(message, cancellationToken);
43+
44+
mockTarget1.Verify(x => x.HandleAsync(message, cancellationToken), Times.Once);
45+
mockTarget2.Verify(x => x.HandleAsync(message, cancellationToken), Times.Once);
46+
}
47+
}
48+
49+
50+
[Fact]
51+
public async Task PublishOnBackgroundThreadAsync_CallsPublishAsyncWithBackgroundMarshaller()
52+
{
53+
var eventAggregator = new EventAggregator();
54+
var message = new object();
55+
using (var tokenSource = new CancellationTokenSource())
56+
{
57+
var cancellationToken = tokenSource.Token;
58+
var mockTarget1 = new Mock<IHandle<object>>();
59+
eventAggregator.SubscribeOnPublishedThread(mockTarget1.Object);
60+
61+
62+
await eventAggregator.PublishOnBackgroundThreadAsync(message, cancellationToken);
63+
64+
mockTarget1.Verify(x => x.HandleAsync(message, cancellationToken), Times.Once);
65+
}
66+
}
67+
68+
[Fact]
69+
public async Task PublishOnCurrentThreadAsync_CallsHandleAsyncOnAllSubscribedTargets()
70+
{
71+
var eventAggregator = new EventAggregator();
72+
string message = "Test";
73+
using (var tokenSource = new CancellationTokenSource())
74+
{
75+
var cancellationToken = tokenSource.Token;
76+
77+
// Create 20 mock targets
78+
var mockTargets = new Mock<IHandle<string>>[NumberOfMockTargets];
79+
for (int i = 0; i < mockTargets.Length; i++)
80+
{
81+
mockTargets[i] = new Mock<IHandle<string>>();
82+
eventAggregator.SubscribeOnPublishedThread(mockTargets[i].Object);
83+
}
84+
85+
await eventAggregator.PublishOnCurrentThreadAsync(message, cancellationToken);
86+
87+
// Verify HandleAsync was called on each
88+
foreach (var mockTarget in mockTargets)
89+
{
90+
mockTarget.Verify(x => x.HandleAsync(message, cancellationToken), Times.Once);
91+
}
92+
}
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)