Skip to content

Commit

Permalink
Do not continue asserting on the concrete exception type when the exc…
Browse files Browse the repository at this point in the history
…eption is `null` (#2398)

* Improved the failure message for `ThrowExactly[Async]`

* Add release notes

Co-authored-by: Jonas Nyrup <jnyrup@users.noreply.github.com>

---------

Co-authored-by: IT-VBFK <it@voecklabrucker-freikriche.at>
Co-authored-by: Jonas Nyrup <jnyrup@users.noreply.github.com>
  • Loading branch information
3 people committed Oct 22, 2023
1 parent 4ac2689 commit 0ae4aa3
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 4 deletions.
7 changes: 5 additions & 2 deletions Src/FluentAssertions/Specialized/AsyncFunctionAssertions.cs
Expand Up @@ -91,12 +91,15 @@ protected AsyncFunctionAssertions(Func<TTask> subject, IExtractExceptions extrac
{
Exception exception = await InvokeWithInterceptionAsync(Subject);

Execute.Assertion
success = Execute.Assertion
.ForCondition(exception is not null)
.BecauseOf(because, becauseArgs)
.FailWith("Expected {0}{reason}, but no exception was thrown.", expectedType);

exception.Should().BeOfType(expectedType, because, becauseArgs);
if (success)
{
exception.Should().BeOfType(expectedType, because, becauseArgs);
}

return new ExceptionAssertions<TException>(new[] { exception as TException });
}
Expand Down
7 changes: 5 additions & 2 deletions Src/FluentAssertions/Specialized/DelegateAssertions.cs
Expand Up @@ -113,12 +113,15 @@ public AndConstraint<TAssertions> NotThrow<TException>(string because = "", para

Type expectedType = typeof(TException);

Execute.Assertion
success = Execute.Assertion
.ForCondition(exception is not null)
.BecauseOf(because, becauseArgs)
.FailWith("Expected {0}{reason}, but no exception was thrown.", expectedType);

exception.Should().BeOfType(expectedType, because, becauseArgs);
if (success)
{
exception.Should().BeOfType(expectedType, because, becauseArgs);
}

return new ExceptionAssertions<TException>(new[] { exception as TException });
}
Expand Down
20 changes: 20 additions & 0 deletions Tests/FluentAssertions.Specs/Specialized/DelegateAssertionSpecs.cs
@@ -1,4 +1,6 @@
using System;
using System.Threading.Tasks;
using FluentAssertions.Execution;
using FluentAssertions.Specialized;
using Xunit;

Expand Down Expand Up @@ -34,4 +36,22 @@ public void When_injecting_a_null_clock_it_should_throw()
act.Should().ThrowExactly<ArgumentNullException>()
.WithParameterName("clock");
}

public class ThrowExactly
{
[Fact]
public void Does_not_continue_assertion_on_exact_exception_type()
{
// Arrange
var a = () => { };

// Act
using var scope = new AssertionScope();
a.Should().ThrowExactly<InvalidOperationException>();

// Assert
scope.Discard().Should().ContainSingle()
.Which.Should().Match("*InvalidOperationException*no exception*");
}
}
}
19 changes: 19 additions & 0 deletions Tests/FluentAssertions.Specs/Specialized/TaskAssertionSpecs.cs
Expand Up @@ -3,6 +3,7 @@
using System.Threading.Tasks;
using FluentAssertions.Execution;
using FluentAssertions.Extensions;
using FluentAssertions.Specialized;
using Xunit;
using Xunit.Sdk;
using static FluentAssertions.FluentActions;
Expand Down Expand Up @@ -505,6 +506,24 @@ public async Task When_task_throws_unexpected_exception_asynchronous_it_should_f
}
}

public class ThrowExactlyAsync
{
[Fact]
public async Task Does_not_continue_assertion_on_exact_exception_type()
{
// Arrange
var a = () => Task.Delay(1);

// Act
using var scope = new AssertionScope();
await a.Should().ThrowExactlyAsync<InvalidOperationException>();

// Assert
scope.Discard().Should().ContainSingle()
.Which.Should().Match("*InvalidOperationException*no exception*");
}
}

[Collection("UIFacts")]
public class CompleteWithinAsyncUIFacts
{
Expand Down
2 changes: 2 additions & 0 deletions docs/_pages/releases.md
Expand Up @@ -25,6 +25,8 @@ sidebar:
* Capitalize `true` and `false` in failure messages and make them formattable to a custom `BooleanFormatter` - [#2390](https://github.com/fluentassertions/fluentassertions/pull/2390), [#2393](https://github.com/fluentassertions/fluentassertions/pull/2393)
* Improved the failure message for `NotBeOfType` when wrapped in an `AssertionScope` and the subject is null - [#2399](https://github.com/fluentassertions/fluentassertions/pull/2399)
* Improved the failure message for `BeWritable`/`BeReadable` when wrapped in an `AssertionScope` and the subject is read-only/write-only - [#2399](https://github.com/fluentassertions/fluentassertions/pull/2399)
* Improved the failure message for `ThrowExactly[Async]` when wrapped in an `AssertionScope` and no exception is thrown - [#2398](https://github.com/fluentassertions/fluentassertions/pull/2398)


### Breaking Changes (for users)
* Moved support for `DataSet`, `DataTable`, `DataRow` and `DataColumn` into a new package `FluentAssertions.DataSet` - [#2267](https://github.com/fluentassertions/fluentassertions/pull/2267)
Expand Down

0 comments on commit 0ae4aa3

Please sign in to comment.