Move non-generic `NotThrow[After]` to `ActionAssertions` by jnyrup · Pull Request #2371 · fluentassertions/fluentassertions · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions Src/FluentAssertions/Specialized/ActionAssertions.cs
95 changes: 2 additions & 93 deletions Src/FluentAssertions/Specialized/DelegateAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,33 +81,6 @@ public AndConstraint<TAssertions> NotThrow<TException>(string because = "", para
return new AndConstraint<TAssertions>((TAssertions)this);
}

/// <summary>
/// Asserts that the current <see cref="Delegate" /> does not throw any exception.
/// </summary>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
/// </param>
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
public AndConstraint<TAssertions> NotThrow(string because = "", params object[] becauseArgs)
{
bool success = Execute.Assertion
.ForCondition(Subject is not null)
.BecauseOf(because, becauseArgs)
.FailWith("Expected {context} not to throw{reason}, but found <null>.");

if (success)
{
FailIfSubjectIsAsyncVoid();
Exception exception = InvokeSubjectWithInterception();
return NotThrowInternal(exception, because, becauseArgs);
}

return new AndConstraint<TAssertions>((TAssertions)this);
}

/// <summary>
/// Asserts that the current <see cref="Delegate"/> throws an exception of the exact type <typeparamref name="TException"/> (and not a derived exception type).
/// </summary>
Expand Down Expand Up @@ -153,73 +126,9 @@ public ExceptionAssertions<TException> ThrowExactly<TException>(string because =
return new ExceptionAssertions<TException>(Array.Empty<TException>());
}

/// <summary>
/// Asserts that the current <see cref="Delegate"/> stops throwing any exception
/// after a specified amount of time.
/// </summary>
/// <remarks>
/// The delegate is invoked. If it raises an exception,
/// the invocation is repeated until it either stops raising any exceptions
/// or the specified wait time is exceeded.
/// </remarks>
/// <param name="waitTime">
/// The time after which the delegate should have stopped throwing any exception.
/// </param>
/// <param name="pollInterval">
/// The time between subsequent invocations of the delegate.
/// </param>
/// <param name="because">
/// A formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the assertion
/// is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
/// </param>
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="waitTime"/> or <paramref name="pollInterval"/> are negative.</exception>
public AndConstraint<TAssertions> NotThrowAfter(TimeSpan waitTime, TimeSpan pollInterval, string because = "",
params object[] becauseArgs)
{
Guard.ThrowIfArgumentIsNegative(waitTime);
Guard.ThrowIfArgumentIsNegative(pollInterval);

bool success = Execute.Assertion
.ForCondition(Subject is not null)
.BecauseOf(because, becauseArgs)
.FailWith("Expected {context} not to throw after {0}{reason}, but found <null>.", waitTime);

if (success)
{
FailIfSubjectIsAsyncVoid();

TimeSpan? invocationEndTime = null;
Exception exception = null;
ITimer timer = Clock.StartTimer();

while (invocationEndTime is null || invocationEndTime < waitTime)
{
exception = InvokeSubjectWithInterception();

if (exception is null)
{
break;
}

Clock.Delay(pollInterval);
invocationEndTime = timer.Elapsed;
}

Execute.Assertion
.BecauseOf(because, becauseArgs)
.ForCondition(exception is null)
.FailWith("Did not expect any exceptions after {0}{reason}, but found {1}.", waitTime, exception);
}

return new AndConstraint<TAssertions>((TAssertions)this);
}

protected abstract void InvokeSubject();

private Exception InvokeSubjectWithInterception()
private protected Exception InvokeSubjectWithInterception()
{
Exception actualException = null;

Expand Down Expand Up @@ -248,7 +157,7 @@ private Exception InvokeSubjectWithInterception()
return actualException;
}

private void FailIfSubjectIsAsyncVoid()
private protected void FailIfSubjectIsAsyncVoid()
{
if (Subject.GetMethodInfo().IsDecoratedWithOrInherit<AsyncStateMachineAttribute>())
{
Expand Down
4 changes: 2 additions & 2 deletions Src/FluentAssertions/Specialized/FunctionAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected override void InvokeSubject()
/// <param name="becauseArgs">
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
public new AndWhichConstraint<FunctionAssertions<T>, T> NotThrow(string because = "", params object[] becauseArgs)
public AndWhichConstraint<FunctionAssertions<T>, T> NotThrow(string because = "", params object[] becauseArgs)
{
bool success = Execute.Assertion
.ForCondition(Subject is not null)
Expand Down Expand Up @@ -78,7 +78,7 @@ protected override void InvokeSubject()
/// Zero or more objects to format using the placeholders in <paramref name="because" />.
/// </param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="waitTime"/> or <paramref name="pollInterval"/> are negative.</exception>
public new AndWhichConstraint<FunctionAssertions<T>, T> NotThrowAfter(TimeSpan waitTime, TimeSpan pollInterval,
public AndWhichConstraint<FunctionAssertions<T>, T> NotThrowAfter(TimeSpan waitTime, TimeSpan pollInterval,
string because = "", params object[] becauseArgs)
{
bool success = Execute.Assertion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2088,6 +2088,8 @@ namespace FluentAssertions.Specialized
public ActionAssertions(System.Action subject, FluentAssertions.Specialized.IExtractExceptions extractor, FluentAssertions.Common.IClock clock) { }
protected override string Identifier { get; }
protected override void InvokeSubject() { }
public FluentAssertions.AndConstraint<FluentAssertions.Specialized.ActionAssertions> NotThrow(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<FluentAssertions.Specialized.ActionAssertions> NotThrowAfter(System.TimeSpan waitTime, System.TimeSpan pollInterval, string because = "", params object[] becauseArgs) { }
}
public class AsyncFunctionAssertions<TTask, TAssertions> : FluentAssertions.Specialized.DelegateAssertionsBase<System.Func<TTask>, TAssertions>
where TTask : System.Threading.Tasks.Task
Expand Down Expand Up @@ -2121,10 +2123,8 @@ namespace FluentAssertions.Specialized
{
protected DelegateAssertions(TDelegate @delegate, FluentAssertions.Specialized.IExtractExceptions extractor) { }
protected abstract void InvokeSubject();
public FluentAssertions.AndConstraint<TAssertions> NotThrow(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotThrow<TException>(string because = "", params object[] becauseArgs)
where TException : System.Exception { }
public FluentAssertions.AndConstraint<TAssertions> NotThrowAfter(System.TimeSpan waitTime, System.TimeSpan pollInterval, string because = "", params object[] becauseArgs) { }
public FluentAssertions.Specialized.ExceptionAssertions<TException> Throw<TException>(string because = "", params object[] becauseArgs)
where TException : System.Exception { }
public FluentAssertions.Specialized.ExceptionAssertions<TException> ThrowExactly<TException>(string because = "", params object[] becauseArgs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2209,6 +2209,8 @@ namespace FluentAssertions.Specialized
public ActionAssertions(System.Action subject, FluentAssertions.Specialized.IExtractExceptions extractor, FluentAssertions.Common.IClock clock) { }
protected override string Identifier { get; }
protected override void InvokeSubject() { }
public FluentAssertions.AndConstraint<FluentAssertions.Specialized.ActionAssertions> NotThrow(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<FluentAssertions.Specialized.ActionAssertions> NotThrowAfter(System.TimeSpan waitTime, System.TimeSpan pollInterval, string because = "", params object[] becauseArgs) { }
}
public class AsyncFunctionAssertions<TTask, TAssertions> : FluentAssertions.Specialized.DelegateAssertionsBase<System.Func<TTask>, TAssertions>
where TTask : System.Threading.Tasks.Task
Expand Down Expand Up @@ -2242,10 +2244,8 @@ namespace FluentAssertions.Specialized
{
protected DelegateAssertions(TDelegate @delegate, FluentAssertions.Specialized.IExtractExceptions extractor) { }
protected abstract void InvokeSubject();
public FluentAssertions.AndConstraint<TAssertions> NotThrow(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotThrow<TException>(string because = "", params object[] becauseArgs)
where TException : System.Exception { }
public FluentAssertions.AndConstraint<TAssertions> NotThrowAfter(System.TimeSpan waitTime, System.TimeSpan pollInterval, string because = "", params object[] becauseArgs) { }
public FluentAssertions.Specialized.ExceptionAssertions<TException> Throw<TException>(string because = "", params object[] becauseArgs)
where TException : System.Exception { }
public FluentAssertions.Specialized.ExceptionAssertions<TException> ThrowExactly<TException>(string because = "", params object[] becauseArgs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,8 @@ namespace FluentAssertions.Specialized
public ActionAssertions(System.Action subject, FluentAssertions.Specialized.IExtractExceptions extractor, FluentAssertions.Common.IClock clock) { }
protected override string Identifier { get; }
protected override void InvokeSubject() { }
public FluentAssertions.AndConstraint<FluentAssertions.Specialized.ActionAssertions> NotThrow(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<FluentAssertions.Specialized.ActionAssertions> NotThrowAfter(System.TimeSpan waitTime, System.TimeSpan pollInterval, string because = "", params object[] becauseArgs) { }
}
public class AsyncFunctionAssertions<TTask, TAssertions> : FluentAssertions.Specialized.DelegateAssertionsBase<System.Func<TTask>, TAssertions>
where TTask : System.Threading.Tasks.Task
Expand Down Expand Up @@ -2072,10 +2074,8 @@ namespace FluentAssertions.Specialized
{
protected DelegateAssertions(TDelegate @delegate, FluentAssertions.Specialized.IExtractExceptions extractor) { }
protected abstract void InvokeSubject();
public FluentAssertions.AndConstraint<TAssertions> NotThrow(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotThrow<TException>(string because = "", params object[] becauseArgs)
where TException : System.Exception { }
public FluentAssertions.AndConstraint<TAssertions> NotThrowAfter(System.TimeSpan waitTime, System.TimeSpan pollInterval, string because = "", params object[] becauseArgs) { }
public FluentAssertions.Specialized.ExceptionAssertions<TException> Throw<TException>(string because = "", params object[] becauseArgs)
where TException : System.Exception { }
public FluentAssertions.Specialized.ExceptionAssertions<TException> ThrowExactly<TException>(string because = "", params object[] becauseArgs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2088,6 +2088,8 @@ namespace FluentAssertions.Specialized
public ActionAssertions(System.Action subject, FluentAssertions.Specialized.IExtractExceptions extractor, FluentAssertions.Common.IClock clock) { }
protected override string Identifier { get; }
protected override void InvokeSubject() { }
public FluentAssertions.AndConstraint<FluentAssertions.Specialized.ActionAssertions> NotThrow(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<FluentAssertions.Specialized.ActionAssertions> NotThrowAfter(System.TimeSpan waitTime, System.TimeSpan pollInterval, string because = "", params object[] becauseArgs) { }
}
public class AsyncFunctionAssertions<TTask, TAssertions> : FluentAssertions.Specialized.DelegateAssertionsBase<System.Func<TTask>, TAssertions>
where TTask : System.Threading.Tasks.Task
Expand Down Expand Up @@ -2121,10 +2123,8 @@ namespace FluentAssertions.Specialized
{
protected DelegateAssertions(TDelegate @delegate, FluentAssertions.Specialized.IExtractExceptions extractor) { }
protected abstract void InvokeSubject();
public FluentAssertions.AndConstraint<TAssertions> NotThrow(string because = "", params object[] becauseArgs) { }
public FluentAssertions.AndConstraint<TAssertions> NotThrow<TException>(string because = "", params object[] becauseArgs)
where TException : System.Exception { }
public FluentAssertions.AndConstraint<TAssertions> NotThrowAfter(System.TimeSpan waitTime, System.TimeSpan pollInterval, string because = "", params object[] becauseArgs) { }
public FluentAssertions.Specialized.ExceptionAssertions<TException> Throw<TException>(string because = "", params object[] becauseArgs)
where TException : System.Exception { }
public FluentAssertions.Specialized.ExceptionAssertions<TException> ThrowExactly<TException>(string because = "", params object[] becauseArgs)
Expand Down
1 change: 1 addition & 0 deletions docs/_pages/releases.md