Skip to content

Commit 822d005

Browse files
authored
Adds overloads with TimeSpan timeouts to AssertEx methods (#155)
1 parent b91bb2c commit 822d005

File tree

3 files changed

+79
-31
lines changed

3 files changed

+79
-31
lines changed

src/ReactiveDomain.Foundation.Tests/when_using_read_model_base.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void can_start_streams_by_aggregate()
6262
var s1 = Namer.GenerateForAggregate(typeof(TestAggregate), aggId);
6363
AppendEvents(1, _conn, s1, 7);
6464
Start<TestAggregate>(aggId);
65-
AssertEx.AtLeastModelVersion(this, 2, 1000, msg: $"Expected 2 got {Version}"); // 1 message + CatchupSubscriptionBecameLive
65+
AssertEx.AtLeastModelVersion(this, 2, msg: $"Expected 2 got {Version}"); // 1 message + CatchupSubscriptionBecameLive
6666
AssertEx.IsOrBecomesTrue(() => Sum == 7);
6767
}
6868
[Fact]
@@ -75,14 +75,14 @@ public void can_start_streams_by_aggregate_category()
7575
AppendEvents(1, _conn, s2, 5);
7676
Start<ReadModelTestCategoryAggregate>(null, true);
7777

78-
AssertEx.AtLeastModelVersion(this, 3, 1000, msg: $"Expected 3 got {Version}");
78+
AssertEx.AtLeastModelVersion(this, 3, msg: $"Expected 3 got {Version}");
7979
AssertEx.IsOrBecomesTrue(() => Sum == 12);
8080
}
8181
[Fact]
8282
public void can_read_one_stream()
8383
{
8484
Start(_stream1);
85-
AssertEx.AtLeastModelVersion(this, 11, 1000, msg: $"Expected 11 got {Version}");
85+
AssertEx.AtLeastModelVersion(this, 11, msg: $"Expected 11 got {Version}");
8686
AssertEx.IsOrBecomesTrue(() => Sum == 20);
8787
//confirm checkpoints
8888
Assert.Equal(_stream1, GetCheckpoint()[0].Item1);
@@ -93,7 +93,7 @@ public void can_read_two_streams()
9393
{
9494
Start(_stream1);
9595
Start(_stream2);
96-
AssertEx.AtLeastModelVersion(this, 22, 1000, msg: $"Expected 22 got {Version}");
96+
AssertEx.AtLeastModelVersion(this, 22, msg: $"Expected 22 got {Version}");
9797
AssertEx.IsOrBecomesTrue(() => Sum == 50);
9898
//confirm checkpoints
9999
Assert.Equal(_stream1, GetCheckpoint()[0].Item1);
@@ -105,29 +105,29 @@ public void can_read_two_streams()
105105
public void can_wait_for_one_stream_to_go_live()
106106
{
107107
Start(_stream1, null, true);
108-
AssertEx.AtLeastModelVersion(this, 11, 100, msg: $"Expected 11 got {Version}");
108+
AssertEx.AtLeastModelVersion(this, 11, TimeSpan.FromMilliseconds(100), msg: $"Expected 11 got {Version}");
109109
AssertEx.IsOrBecomesTrue(() => Sum == 20, 100);
110110
}
111111
[Fact]
112112
public void can_wait_for_two_streams_to_go_live()
113113
{
114114
Start(_stream1, null, true);
115-
AssertEx.AtLeastModelVersion(this, 11, 100, msg: $"Expected 11 got {Version}");
115+
AssertEx.AtLeastModelVersion(this, 11, TimeSpan.FromMilliseconds(100), msg: $"Expected 11 got {Version}");
116116
AssertEx.IsOrBecomesTrue(() => Sum == 20, 150);
117117

118118
Start(_stream2, null, true);
119-
AssertEx.AtLeastModelVersion(this, 21, 100, msg: $"Expected 21 got {Version}");
119+
AssertEx.AtLeastModelVersion(this, 21, TimeSpan.FromMilliseconds(100), msg: $"Expected 21 got {Version}");
120120
AssertEx.IsOrBecomesTrue(() => Sum == 50, 150);
121121
}
122122
[Fact]
123123
public void can_listen_to_one_stream()
124124
{
125125
Start(_stream1);
126-
AssertEx.AtLeastModelVersion(this, 11, 1000, msg: $"Expected 11 got {Version}");
126+
AssertEx.AtLeastModelVersion(this, 11, msg: $"Expected 11 got {Version}");
127127
AssertEx.IsOrBecomesTrue(() => Sum == 20);
128128
//add more messages
129129
AppendEvents(10, _conn, _stream1, 5);
130-
AssertEx.AtLeastModelVersion(this, 21, 1000, msg: $"Expected 21 got {Version}");
130+
AssertEx.AtLeastModelVersion(this, 21, msg: $"Expected 21 got {Version}");
131131
AssertEx.IsOrBecomesTrue(() => Sum == 70);
132132
//confirm checkpoints
133133
Assert.Equal(_stream1, GetCheckpoint()[0].Item1);
@@ -139,12 +139,12 @@ public void can_listen_to_two_streams()
139139
{
140140
Start(_stream1);
141141
Start(_stream2);
142-
AssertEx.AtLeastModelVersion(this, 22, 1000, msg: $"Expected 22 got {Version}");
142+
AssertEx.AtLeastModelVersion(this, 22, msg: $"Expected 22 got {Version}");
143143
AssertEx.IsOrBecomesTrue(() => Sum == 50);
144144
//add more messages
145145
AppendEvents(10, _conn, _stream1, 5);
146146
AppendEvents(10, _conn, _stream2, 7);
147-
AssertEx.AtLeastModelVersion(this, 42, 1000, msg: $"Expected 42 got {Version}");
147+
AssertEx.AtLeastModelVersion(this, 42, msg: $"Expected 42 got {Version}");
148148
AssertEx.IsOrBecomesTrue(() => Sum == 170);
149149
//confirm checkpoints
150150
Assert.Equal(_stream1, GetCheckpoint()[0].Item1);
@@ -161,11 +161,11 @@ public void can_use_checkpoint_on_one_stream()
161161
//start at the checkpoint
162162
Start(_stream1, checkPoint);
163163
//add the one recorded event
164-
AssertEx.AtLeastModelVersion(this, 2, 100, msg: $"Expected 2 got {Version}");
164+
AssertEx.AtLeastModelVersion(this, 2, TimeSpan.FromMilliseconds(100), msg: $"Expected 2 got {Version}");
165165
AssertEx.IsOrBecomesTrue(() => Sum == 20);
166166
//add more messages
167167
AppendEvents(10, _conn, _stream1, 5);
168-
AssertEx.AtLeastModelVersion(this, 12, 100, msg: $"Expected 12 got {Version}");
168+
AssertEx.AtLeastModelVersion(this, 12, TimeSpan.FromMilliseconds(100), msg: $"Expected 12 got {Version}");
169169
AssertEx.IsOrBecomesTrue(() => Sum == 70);
170170
//confirm checkpoints
171171
Assert.Equal(_stream1, GetCheckpoint()[0].Item1);
@@ -181,12 +181,12 @@ public void can_use_checkpoint_on_two_streams()
181181
Start(_stream1, checkPoint1);
182182
Start(_stream2, checkPoint2);
183183
//add the recorded events 2 on stream 1 & 5 on stream 2
184-
AssertEx.AtLeastModelVersion(this, 7, 1000, msg: $"Expected 7 got {Version}");
184+
AssertEx.AtLeastModelVersion(this, 7, msg: $"Expected 7 got {Version}");
185185
AssertEx.IsOrBecomesTrue(() => Sum == 50, msg: $"Expected 50 got {Sum}");
186186
//add more messages
187187
AppendEvents(10, _conn, _stream1, 5);
188188
AppendEvents(10, _conn, _stream2, 7);
189-
AssertEx.AtLeastModelVersion(this, 27, 1000, msg: $"Expected 27 got {Version}");
189+
AssertEx.AtLeastModelVersion(this, 27, msg: $"Expected 27 got {Version}");
190190
AssertEx.IsOrBecomesTrue(() => Sum == 170);
191191
//confirm checkpoints
192192
Assert.Equal(_stream1, GetCheckpoint()[0].Item1);
@@ -203,11 +203,11 @@ public void can_listen_to_the_same_stream_twice()
203203
Start(_stream1);
204204
Start(_stream1);
205205
//double events
206-
AssertEx.AtLeastModelVersion(this, 22, 1000, msg: $"Expected 22 got {Version}");
206+
AssertEx.AtLeastModelVersion(this, 22, msg: $"Expected 22 got {Version}");
207207
AssertEx.IsOrBecomesTrue(() => Sum == 40);
208208
//even more doubled events
209209
AppendEvents(10, _conn, _stream1, 5);
210-
AssertEx.AtLeastModelVersion(this, 42, 2000, msg: $"Expected 42 got {Version}");
210+
AssertEx.AtLeastModelVersion(this, 42, TimeSpan.FromSeconds(2), msg: $"Expected 42 got {Version}");
211211
AssertEx.IsOrBecomesTrue(() => Sum == 140);
212212
}
213213

src/ReactiveDomain.Testing/AssertEx.cs

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
using System;
2-
using System.Data.SqlTypes;
32
using System.Threading;
4-
using System.Threading.Tasks;
53
using ReactiveDomain.Foundation;
64
using ReactiveDomain.Messaging.Bus;
7-
using ReactiveDomain.Util;
85
using Xunit;
96

107

@@ -42,6 +39,23 @@ public static void ArraySegmentEqual<T>(
4239
}
4340
}
4441

42+
/// <summary>
43+
/// Asserts the given function will return false before the timeout expires.
44+
/// Repeatedly evaluates the function until false is returned or the timeout expires.
45+
/// Will return immediately when the condition is false.
46+
/// Evaluates the condition on an exponential back off up to 250 ms until timeout.
47+
/// Will yield the thread after each evaluation.
48+
/// </summary>
49+
/// <param name="func">The function to evaluate.</param>
50+
/// <param name="timeout">The timeout.</param>
51+
/// <param name="msg">A message to display if the condition is not satisfied.</param>
52+
public static void IsOrBecomesFalse(Func<bool> func, TimeSpan timeout, string msg = null)
53+
{
54+
if (timeout <= TimeSpan.Zero)
55+
throw new ArgumentException("Timeout must be greater than zero", nameof(timeout));
56+
IsOrBecomesFalse(func, (int)timeout.TotalMilliseconds, msg);
57+
}
58+
4559
/// <summary>
4660
/// Asserts the given function will return false before the timeout expires.
4761
/// Repeatedly evaluates the function until false is returned or the timeout expires.
@@ -52,12 +66,29 @@ public static void ArraySegmentEqual<T>(
5266
/// <param name="func">The function to evaluate.</param>
5367
/// <param name="timeout">A timeout in milliseconds. If not specified, defaults to 1000.</param>
5468
/// <param name="msg">A message to display if the condition is not satisfied.</param>
55-
/// <param name="yieldThread">Ignored, will be removed in a future release</param>
69+
/// <param name="yieldThread">Ignored, will be removed in a future release.</param>
5670
public static void IsOrBecomesFalse(Func<bool> func, int? timeout = null, string msg = null, bool yieldThread = false)
5771
{
5872
IsOrBecomesTrue(() => !func(), timeout, msg);
5973
}
6074

75+
/// <summary>
76+
/// Asserts the given function will return true before the timeout expires.
77+
/// Repeatedly evaluates the function until true is returned or the timeout expires.
78+
/// Will return immediately when the condition is true.
79+
/// Evaluates the condition on an exponential back off up to 250 ms until timeout.
80+
/// Will yield the thread after each evaluation.
81+
/// </summary>
82+
/// <param name="func">The function to evaluate.</param>
83+
/// <param name="timeout">The timeout.</param>
84+
/// <param name="msg">A message to display if the condition is not satisfied.</param>
85+
public static void IsOrBecomesTrue(Func<bool> func, TimeSpan timeout, string msg = null)
86+
{
87+
if (timeout <= TimeSpan.Zero)
88+
throw new ArgumentException("Timeout must be greater than zero", nameof(timeout));
89+
IsOrBecomesTrue(func, (int)timeout.TotalMilliseconds, msg);
90+
}
91+
6192
/// <summary>
6293
/// Asserts the given function will return true before the timeout expires.
6394
/// Repeatedly evaluates the function until true is returned or the timeout expires.
@@ -68,10 +99,10 @@ public static void IsOrBecomesFalse(Func<bool> func, int? timeout = null, string
6899
/// <param name="func">The function to evaluate.</param>
69100
/// <param name="timeout">A timeout in milliseconds. If not specified, defaults to 1000.</param>
70101
/// <param name="msg">A message to display if the condition is not satisfied.</param>
71-
/// <param name="yieldThread">Ignored, will be removed in a future release</param>
102+
/// <param name="yieldThread">Ignored, will be removed in a future release.</param>
72103
public static void IsOrBecomesTrue(Func<bool> func, int? timeout = null, string msg = null, bool yieldThread = false)
73104
{
74-
if (func() == true)
105+
if (func())
75106
{
76107
Assert.True(true, msg ?? "");
77108
return;
@@ -104,7 +135,24 @@ public static void IsOrBecomesTrue(Func<bool> func, int? timeout = null, string
104135

105136
/// <summary>
106137
/// Asserts that the given read model will have at least the expected version before the
107-
/// timeout expires. If a test needs to check an exact model version use 'IsOrBecomesTrue(()=> ReadModel.Version == [expectedVersion], [timeout])'.
138+
/// timeout expires. If a test needs to check an exact model version use
139+
/// 'IsOrBecomesTrue(()=> ReadModel.Version == [expectedVersion], [timeout])'.
140+
/// </summary>
141+
/// <param name="readModel">The read model.</param>
142+
/// <param name="expectedVersion">The read model's expected minimum version.</param>
143+
/// <param name="timeout">The timeout.</param>
144+
/// <param name="msg">A message to display if the condition is not satisfied.</param>
145+
public static void AtLeastModelVersion(ReadModelBase readModel, int expectedVersion, TimeSpan timeout, string msg = null)
146+
{
147+
if (timeout <= TimeSpan.Zero)
148+
throw new ArgumentException("Timeout must be greater than zero", nameof(timeout));
149+
AtLeastModelVersion(readModel, expectedVersion, (int)timeout.TotalMilliseconds, msg);
150+
}
151+
152+
/// <summary>
153+
/// Asserts that the given read model will have at least the expected version before the
154+
/// timeout expires. If a test needs to check an exact model version use
155+
/// 'IsOrBecomesTrue(()=> ReadModel.Version == [expectedVersion], [timeout])'.
108156
/// </summary>
109157
/// <param name="readModel">The read model.</param>
110158
/// <param name="expectedVersion">The read model's expected minimum version.</param>
@@ -120,7 +168,7 @@ public static void AtLeastModelVersion(ReadModelBase readModel, int expectedVers
120168
/// The current thread will yield at the start of the delay.
121169
/// </summary>
122170
/// <param name="func">The function to evaluate.</param>
123-
/// <param name="delay">A delay timeSpan.</param>
171+
/// <param name="delay">A delay <see cref="TimeSpan"/>.</param>
124172
public static bool EvaluateAfterDelay(Func<bool> func, TimeSpan delay)
125173
{
126174
Thread.Sleep(delay);

src/ReactiveDomain.Testing/EventStore/StreamStoreSubscriptionTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,12 @@ public void can_subscribe_to_stream_from()
119119
(reason, ex) => dropped = true);
120120

121121

122-
AssertEx.IsOrBecomesTrue(() => liveProcessingStarted, 2000, msg: "Failed handle live processing start");
123-
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) == 2, 5000, msg: $"Expected 2 Events got { Interlocked.Read(ref evtCount)}");
122+
AssertEx.IsOrBecomesTrue(() => liveProcessingStarted, TimeSpan.FromSeconds(2), msg: "Failed handle live processing start");
123+
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) == 2, TimeSpan.FromSeconds(5), msg: $"Expected 2 Events got { Interlocked.Read(ref evtCount)}");
124124
Task.Run(() => AppendEvents(5, conn, streamName));
125-
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) == 7, 5000, msg: $"Expected 7 Events got { Interlocked.Read(ref evtCount)}");
125+
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) == 7, TimeSpan.FromSeconds(5), msg: $"Expected 7 Events got { Interlocked.Read(ref evtCount)}");
126126
AppendEvents(5, conn, streamName);
127-
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) == 12, 5000, msg: $"Expected 12 Events got { Interlocked.Read(ref evtCount)}");
127+
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) == 12, TimeSpan.FromSeconds(5), msg: $"Expected 12 Events got { Interlocked.Read(ref evtCount)}");
128128
sub.Dispose();
129129
AssertEx.IsOrBecomesTrue(() => dropped, msg: "Failed to handle drop");
130130
}
@@ -224,7 +224,7 @@ public void can_subscribe_to_event_type_stream()
224224
conn.TryConfirmStream(stream, 5);
225225
}
226226
Assert.False(dropped);
227-
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) >= 10, 2000, $"Expected 10 got {Interlocked.Read(ref evtCount)}");
227+
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) >= 10, TimeSpan.FromSeconds(2), $"Expected 10 got {Interlocked.Read(ref evtCount)}");
228228
sub.Dispose();
229229
AssertEx.IsOrBecomesTrue(() => dropped, msg: "Failed to handle drop");
230230
}
@@ -260,7 +260,7 @@ public void can_subscribe_to_category_stream()
260260
AppendEvents(5, conn, streams[0]);
261261
AppendEvents(5, conn, streams[1]);
262262
Assert.True(conn.TryConfirmStream(streamTypeName, 12), "Stream not ready.");
263-
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) == 10, 2000,
263+
AssertEx.IsOrBecomesTrue(() => Interlocked.Read(ref evtCount) == 10, TimeSpan.FromSeconds(2),
264264
$"Expected 10 got {Interlocked.Read(ref evtCount)} on {conn.ConnectionName}");
265265
sub.Dispose();
266266
AssertEx.IsOrBecomesTrue(() => dropped, msg: "Failed to handle drop");

0 commit comments

Comments
 (0)