1
- using Xunit ;
2
- using Shouldly ;
3
1
using System ;
4
- using System . Threading . Tasks ;
5
2
using System . Threading ;
3
+ using System . Threading . Tasks ;
4
+ using Shouldly ;
5
+ using Xunit ;
6
6
7
7
namespace AsyncBus . Tests
8
8
{
@@ -15,14 +15,6 @@ public BusSpec()
15
15
_bus = BusSetup . CreateBus ( ) ;
16
16
}
17
17
18
- [ Fact ]
19
- internal void Bus_Should_Allow_Registering_Subscriber_Returning_Void ( )
20
- {
21
- void Callback ( string value ) { }
22
-
23
- Should . NotThrow ( ( ) => _bus . SubscribeSync < string > ( Callback ) ) ;
24
- }
25
-
26
18
[ Fact ]
27
19
internal void Bus_Should_Allow_Registering_Subscriber_Returning_Task ( )
28
20
{
@@ -32,81 +24,49 @@ internal void Bus_Should_Allow_Registering_Subscriber_Returning_Task()
32
24
}
33
25
34
26
[ Fact ]
35
- internal void Bus_Should_Allow_Registering_Subscriber_Taking_Cancellation_Token ( )
27
+ internal void Bus_Should_Allow_Registering_Subscriber_Returning_Void ( )
36
28
{
37
- Task Callback ( string value , CancellationToken cancellationToken ) => Task . CompletedTask ;
29
+ void Callback ( string value )
30
+ {
31
+ }
38
32
39
- Should . NotThrow ( ( ) => _bus . Subscribe < string > ( Callback ) ) ;
33
+ Should . NotThrow ( ( ) => _bus . SubscribeSync < string > ( Callback ) ) ;
40
34
}
41
35
42
36
[ Fact ]
43
- internal async Task Subscriber_Should_Not_Be_Called_After_Corresponding_Subscription_Token_Disposed ( )
37
+ internal void Bus_Should_Allow_Registering_Subscriber_Taking_Cancellation_Token ( )
44
38
{
45
- // GIVEN we register a callback to update a local variable.
46
- int ? receivedValue = null ;
47
- void Callback ( int value ) => receivedValue = value ;
48
- var subscriptionToken = _bus . SubscribeSync < int > ( Callback ) ;
49
-
50
- // WHEN we publish a value.
51
- await _bus . Publish ( 3 ) ;
52
-
53
- // THEN the local variable should be this value.
54
- receivedValue . ShouldBe ( 3 ) ;
55
- receivedValue = null ;
56
-
57
- // WHEN we dispose the subscription token.
58
- subscriptionToken . Dispose ( ) ;
59
-
60
- // AND we publish another value.
61
- await _bus . Publish ( 5 ) ;
39
+ Task Callback ( string value , CancellationToken cancellationToken ) => Task . CompletedTask ;
62
40
63
- // THEN the variable should not have been updated.
64
- receivedValue . ShouldBeNull ( ) ;
41
+ Should . NotThrow ( ( ) => _bus . Subscribe < string > ( Callback ) ) ;
65
42
}
66
43
67
44
[ Fact ]
68
- internal async Task Subscription_Should_Be_Covariant ( )
45
+ internal async Task Cancellation_Tokens_Should_Be_Passed_To_Subscribers ( )
69
46
{
70
- // GIVEN we register a callback that handles Parent objects .
71
- Parent receivedParent = null ;
72
- void Callback ( Parent parent ) => receivedParent = parent ;
47
+ // GIVEN a subscriber that accepts a cancellation token is registered to the bus .
48
+ var cancellationRequested = false ;
49
+ var tcs = new TaskCompletionSource < object > ( ) ;
73
50
74
- using ( _bus . SubscribeSync < Parent > ( Callback ) )
51
+ async Task Callback ( int _ , CancellationToken cancellationToken )
75
52
{
76
- // WHEN we publish a child object.
77
- await _bus . Publish ( new Child { Property = 5 } ) ;
78
-
79
- // THEN the subscriber should have received the published child.
80
- receivedParent . ShouldNotBeNull ( ) ;
81
- receivedParent . Property . ShouldBe ( 5 ) ;
53
+ await tcs . Task ;
54
+ cancellationRequested = cancellationToken . IsCancellationRequested ;
82
55
}
83
- }
84
-
85
- [ Fact ]
86
- internal async Task Subscribers_Should_Be_Notified_In_Order_Of_Registration ( )
87
- {
88
- // GIVEN two subscribers register to the bus.
89
- var tcs = new TaskCompletionSource < object > ( ) ;
90
- var secondCallbackCalled = false ;
91
-
92
- Task CallbackA ( int _ ) => tcs . Task ;
93
- void CallbackB ( int _ ) => secondCallbackCalled = true ;
94
56
95
- using ( _bus . Subscribe < int > ( CallbackA ) )
96
- using ( _bus . SubscribeSync < int > ( CallbackB ) )
57
+ using ( _bus . Subscribe < int > ( Callback ) )
97
58
{
98
- // WHEN we publish a message on the bus.
99
- var publicationTask = _bus . Publish ( 3 ) ;
59
+ // WHEN we publish a message with a cancellation token.
60
+ var cts = new CancellationTokenSource ( ) ;
61
+ var publicationTask = _bus . Publish ( 3 , cts . Token ) ;
100
62
101
- // THEN the second callback should not have been called .
102
- secondCallbackCalled . ShouldBeFalse ( ) ;
63
+ // AND we signal cancellation .
64
+ cts . Cancel ( ) ;
103
65
104
- // WHEN we signal completion of the first callback .
66
+ // THEN the subscriber should be notified of that cancellation .
105
67
tcs . SetResult ( null ) ;
106
-
107
- // THEN the second callback should have been called.
108
68
await publicationTask ;
109
- secondCallbackCalled . ShouldBeTrue ( ) ;
69
+ cancellationRequested . ShouldBeTrue ( ) ;
110
70
}
111
71
}
112
72
@@ -123,7 +83,7 @@ async Task CallbackA(int _)
123
83
firstSubscriberNotifiedTcs . SetResult ( null ) ;
124
84
await firstSubscriberBlockTcs . Task ;
125
85
}
126
-
86
+
127
87
void CallbackB ( int _ ) => secondSubscriberNotified = true ;
128
88
129
89
using ( _bus . Subscribe < int > ( CallbackA ) )
@@ -160,55 +120,114 @@ async Task CallbackA(int _)
160
120
}
161
121
162
122
[ Fact ]
163
- internal async Task Cancellation_Tokens_Should_Be_Passed_To_Subscribers ( )
123
+ internal async Task Exceptions_Should_Propagate_From_Subscribers_To_Publication_Task ( )
164
124
{
165
- // GIVEN a subscriber that accepts a cancellation token is registered to the bus .
166
- var cancellationRequested = false ;
167
- var tcs = new TaskCompletionSource < object > ( ) ;
168
- async Task Callback ( int _ , CancellationToken cancellationToken )
125
+ // GIVEN a subscriber that throws an exception when notified .
126
+ void Callback ( int _ ) => throw new ArgumentException ( "All numbers are terrible." ) ;
127
+
128
+ using ( _bus . SubscribeSync < int > ( Callback ) )
169
129
{
170
- await tcs . Task ;
171
- cancellationRequested = cancellationToken . IsCancellationRequested ;
130
+ // EXCEPT an exception is thrown when we publish an integer on the bus.
131
+ var exception = await Should . ThrowAsync < ArgumentException > ( _bus . Publish ( 3 ) ) ;
132
+ exception . Message . ShouldBe ( "All numbers are terrible." ) ;
172
133
}
134
+ }
173
135
174
- using ( _bus . Subscribe < int > ( Callback ) )
136
+ [ Fact ]
137
+ internal async Task Subscriber_Should_Not_Be_Called_After_Corresponding_Subscription_Token_Disposed ( )
138
+ {
139
+ // GIVEN we register a callback to update a local variable.
140
+ int ? receivedValue = null ;
141
+ void Callback ( int value ) => receivedValue = value ;
142
+ var subscriptionToken = _bus . SubscribeSync < int > ( Callback ) ;
143
+
144
+ // WHEN we publish a value.
145
+ await _bus . Publish ( 3 ) ;
146
+
147
+ // THEN the local variable should be this value.
148
+ receivedValue . ShouldBe ( 3 ) ;
149
+ receivedValue = null ;
150
+
151
+ // WHEN we dispose the subscription token.
152
+ subscriptionToken . Dispose ( ) ;
153
+
154
+ // AND we publish another value.
155
+ await _bus . Publish ( 5 ) ;
156
+
157
+ // THEN the variable should not have been updated.
158
+ receivedValue . ShouldBeNull ( ) ;
159
+ }
160
+
161
+ [ Fact ]
162
+ internal async Task Subscribers_Should_Be_Notified_In_Order_Of_Registration ( )
163
+ {
164
+ // GIVEN two subscribers register to the bus.
165
+ var tcs = new TaskCompletionSource < object > ( ) ;
166
+ var secondCallbackCalled = false ;
167
+
168
+ Task CallbackA ( int _ ) => tcs . Task ;
169
+ void CallbackB ( int _ ) => secondCallbackCalled = true ;
170
+
171
+ using ( _bus . Subscribe < int > ( CallbackA ) )
172
+ using ( _bus . SubscribeSync < int > ( CallbackB ) )
175
173
{
176
- // WHEN we publish a message with a cancellation token.
177
- var cts = new CancellationTokenSource ( ) ;
178
- var publicationTask = _bus . Publish ( 3 , cts . Token ) ;
174
+ // WHEN we publish a message on the bus.
175
+ var publicationTask = _bus . Publish ( 3 ) ;
179
176
180
- // AND we signal cancellation .
181
- cts . Cancel ( ) ;
177
+ // THEN the second callback should not have been called .
178
+ secondCallbackCalled . ShouldBeFalse ( ) ;
182
179
183
- // THEN the subscriber should be notified of that cancellation .
180
+ // WHEN we signal completion of the first callback .
184
181
tcs . SetResult ( null ) ;
182
+
183
+ // THEN the second callback should have been called.
185
184
await publicationTask ;
186
- cancellationRequested . ShouldBeTrue ( ) ;
185
+ secondCallbackCalled . ShouldBeTrue ( ) ;
187
186
}
188
-
189
187
}
190
188
191
189
[ Fact ]
192
- internal async Task Exceptions_Should_Propagate_From_Subscribers_To_Publication_Task ( )
190
+ internal async Task Subscription_Should_Be_Contravariant ( )
193
191
{
194
- // GIVEN a subscriber that throws an exception when notified.
195
- void Callback ( int _ ) => throw new ArgumentException ( "All numbers are terrible." ) ;
192
+ // GIVEN we register a callback that handles Parent objects.
193
+ Parent receivedParent = null ;
194
+ void Callback ( Parent parent ) => receivedParent = parent ;
196
195
197
- using ( _bus . SubscribeSync < int > ( Callback ) )
196
+ using ( _bus . SubscribeSync < Parent > ( Callback ) )
198
197
{
199
- // EXCEPT an exception is thrown when we publish an integer on the bus.
200
- var exception = await Should . ThrowAsync < ArgumentException > ( _bus . Publish ( 3 ) ) ;
201
- exception . Message . ShouldBe ( "All numbers are terrible." ) ;
198
+ // WHEN we publish a child object.
199
+ await _bus . Publish ( new Child { Property = 5 } ) ;
200
+
201
+ // THEN the subscriber should have received the published child.
202
+ receivedParent . ShouldNotBeNull ( ) ;
203
+ receivedParent . Property . ShouldBe ( 5 ) ;
202
204
}
203
205
}
204
206
205
- private class Parent
207
+ [ Fact ]
208
+ internal async Task Subscription_Should_Not_Be_Covariant ( )
206
209
{
207
- public int Property { get ; set ; }
210
+ // GIVEN we register a callback that handles Child objects.
211
+ Child receivedChild = null ;
212
+ void Callback ( Child child ) => receivedChild = child ;
213
+
214
+ using ( _bus . SubscribeSync < Child > ( Callback ) )
215
+ {
216
+ // WHEN we publish a parent object.
217
+ await _bus . Publish ( new Parent { Property = 5 } ) ;
218
+
219
+ // THEN the subscriber should not have received the published parent.
220
+ receivedChild . ShouldBeNull ( ) ;
221
+ }
208
222
}
209
223
210
224
private class Child : Parent
211
225
{
212
226
}
227
+
228
+ private class Parent
229
+ {
230
+ public int Property { get ; set ; }
231
+ }
213
232
}
214
233
}
0 commit comments