Skip to content

Commit

Permalink
xunit/xunit#2773: Add Assert.RaisesAny and Assert.RaisesAnyAsync non-…
Browse files Browse the repository at this point in the history
…generic for EventArgs
  • Loading branch information
bradwilson committed Sep 7, 2023
1 parent c0485bd commit 46dfaa9
Showing 1 changed file with 143 additions and 3 deletions.
146 changes: 143 additions & 3 deletions EventAsserts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Xunit
partial class Assert
{
/// <summary>
/// Verifies that a event with the exact event args is raised.
/// Verifies that an event with the exact event args is raised.
/// </summary>
/// <typeparam name="T">The type of the event arguments to expect</typeparam>
/// <param name="attach">Code to attach the event handler</param>
Expand All @@ -45,6 +45,27 @@ partial class Assert
return raisedEvent;
}

/// <summary>
/// Verifies that an event is raised.
/// </summary>
/// <param name="attach">Code to attach the event handler</param>
/// <param name="detach">Code to detach the event handler</param>
/// <param name="testCode">A delegate to the code to be tested</param>
/// <returns>The event sender and arguments wrapped in an object</returns>
/// <exception cref="RaisesException">Thrown when the expected event was not raised.</exception>
public static RaisedEvent<EventArgs> RaisesAny(
Action<EventHandler> attach,
Action<EventHandler> detach,
Action testCode)
{
var raisedEvent = RaisesInternal(attach, detach, testCode);

if (raisedEvent == null)
throw RaisesAnyException.ForNoEvent(typeof(EventArgs));

return raisedEvent;
}

/// <summary>
/// Verifies that an event with the exact or a derived event args is raised.
/// </summary>
Expand All @@ -67,6 +88,27 @@ partial class Assert
return raisedEvent;
}

/// <summary>
/// Verifies that an event is raised.
/// </summary>
/// <param name="attach">Code to attach the event handler</param>
/// <param name="detach">Code to detach the event handler</param>
/// <param name="testCode">A delegate to the code to be tested</param>
/// <returns>The event sender and arguments wrapped in an object</returns>
/// <exception cref="RaisesException">Thrown when the expected event was not raised.</exception>
public static async Task<RaisedEvent<EventArgs>> RaisesAnyAsync(
Action<EventHandler> attach,
Action<EventHandler> detach,
Func<Task> testCode)
{
var raisedEvent = await RaisesAsyncInternal(attach, detach, testCode);

if (raisedEvent == null)
throw RaisesAnyException.ForNoEvent(typeof(EventArgs));

return raisedEvent;
}

/// <summary>
/// Verifies that an event with the exact or a derived event args is raised.
/// </summary>
Expand All @@ -90,6 +132,27 @@ partial class Assert
}

#if XUNIT_VALUETASK
/// <summary>
/// Verifies that an event is raised.
/// </summary>
/// <param name="attach">Code to attach the event handler</param>
/// <param name="detach">Code to detach the event handler</param>
/// <param name="testCode">A delegate to the code to be tested</param>
/// <returns>The event sender and arguments wrapped in an object</returns>
/// <exception cref="RaisesException">Thrown when the expected event was not raised.</exception>
public static async ValueTask<RaisedEvent<EventArgs>> RaisesAnyAsync(
Action<EventHandler> attach,
Action<EventHandler> detach,
Func<ValueTask> testCode)
{
var raisedEvent = await RaisesAsyncInternal(attach, detach, testCode);

if (raisedEvent == null)
throw RaisesAnyException.ForNoEvent(typeof(EventArgs));

return raisedEvent;
}

/// <summary>
/// Verifies that an event with the exact or a derived event args is raised.
/// </summary>
Expand All @@ -114,7 +177,7 @@ partial class Assert
#endif

/// <summary>
/// Verifies that a event with the exact event args (and not a derived type) is raised.
/// Verifies that an event with the exact event args (and not a derived type) is raised.
/// </summary>
/// <typeparam name="T">The type of the event arguments to expect</typeparam>
/// <param name="attach">Code to attach the event handler</param>
Expand All @@ -140,7 +203,7 @@ partial class Assert

#if XUNIT_VALUETASK
/// <summary>
/// Verifies that a event with the exact event args (and not a derived type) is raised.
/// Verifies that an event with the exact event args (and not a derived type) is raised.
/// </summary>
/// <typeparam name="T">The type of the event arguments to expect</typeparam>
/// <param name="attach">Code to attach the event handler</param>
Expand All @@ -163,8 +226,33 @@ partial class Assert

return raisedEvent;
}
#endif

#if XUNIT_NULLABLE
static RaisedEvent<EventArgs>? RaisesInternal(
#else
static RaisedEvent<EventArgs> RaisesInternal(
#endif
Action<EventHandler> attach,
Action<EventHandler> detach,
Action testCode)
{
GuardArgumentNotNull(nameof(attach), attach);
GuardArgumentNotNull(nameof(detach), detach);
GuardArgumentNotNull(nameof(testCode), testCode);

#if XUNIT_NULLABLE
RaisedEvent<EventArgs>? raisedEvent = null;
void handler(object? s, EventArgs args) => raisedEvent = new RaisedEvent<EventArgs>(s, args);
#else
RaisedEvent<EventArgs> raisedEvent = null;
EventHandler handler = (object s, EventArgs args) => raisedEvent = new RaisedEvent<EventArgs>(s, args);
#endif
attach(handler);
testCode();
detach(handler);
return raisedEvent;
}

#if XUNIT_NULLABLE
static RaisedEvent<T>? RaisesInternal<T>(
Expand Down Expand Up @@ -192,6 +280,32 @@ partial class Assert
return raisedEvent;
}

#if XUNIT_NULLABLE
static async Task<RaisedEvent<EventArgs>?> RaisesAsyncInternal(
#else
static async Task<RaisedEvent<EventArgs>> RaisesAsyncInternal(
#endif
Action<EventHandler> attach,
Action<EventHandler> detach,
Func<Task> testCode)
{
GuardArgumentNotNull(nameof(attach), attach);
GuardArgumentNotNull(nameof(detach), detach);
GuardArgumentNotNull(nameof(testCode), testCode);

#if XUNIT_NULLABLE
RaisedEvent<EventArgs>? raisedEvent = null;
void handler(object? s, EventArgs args) => raisedEvent = new RaisedEvent<EventArgs>(s, args);
#else
RaisedEvent<EventArgs> raisedEvent = null;
EventHandler handler = (object s, EventArgs args) => raisedEvent = new RaisedEvent<EventArgs>(s, args);
#endif
attach(handler);
await testCode();
detach(handler);
return raisedEvent;
}

#if XUNIT_NULLABLE
static async Task<RaisedEvent<T>?> RaisesAsyncInternal<T>(
#else
Expand Down Expand Up @@ -219,6 +333,32 @@ partial class Assert
}

#if XUNIT_VALUETASK
#if XUNIT_NULLABLE
static async ValueTask<RaisedEvent<EventArgs>?> RaisesAsyncInternal(
#else
static async Task<RaisedEvent<EventArgs>> RaisesAsyncInternal(
#endif
Action<EventHandler> attach,
Action<EventHandler> detach,
Func<ValueTask> testCode)
{
GuardArgumentNotNull(nameof(attach), attach);
GuardArgumentNotNull(nameof(detach), detach);
GuardArgumentNotNull(nameof(testCode), testCode);

#if XUNIT_NULLABLE
RaisedEvent<EventArgs>? raisedEvent = null;
void handler(object? s, EventArgs args) => raisedEvent = new RaisedEvent<EventArgs>(s, args);
#else
RaisedEvent<EventArgs> raisedEvent = null;
EventHandler handler = (object s, EventArgs args) => raisedEvent = new RaisedEvent<EventArgs>(s, args);
#endif
attach(handler);
await testCode();
detach(handler);
return raisedEvent;
}

#if XUNIT_NULLABLE
static async ValueTask<RaisedEvent<T>?> RaisesAsyncInternal<T>(
#else
Expand Down

0 comments on commit 46dfaa9

Please sign in to comment.