diff --git a/Src/FluentAssertions/AssertionExtensions.Actions.cs b/Src/FluentAssertions/AssertionExtensions.Actions.cs index 1258b18ae1..8b33fd771b 100644 --- a/Src/FluentAssertions/AssertionExtensions.Actions.cs +++ b/Src/FluentAssertions/AssertionExtensions.Actions.cs @@ -64,6 +64,32 @@ public static partial class AssertionExtensions return exceptionAssertions; } + /// + /// Asserts that the subject throws the exact exception (and not a derived exception type). + /// + /// A reference to the method or property. + /// + /// The type of the exception it should throw. + /// + /// + /// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not + /// start with the word because, it is prepended to the message. + /// + /// + /// Zero or more values to use for filling in any compatible placeholders. + /// + /// + /// Returns an object that allows asserting additional members of the thrown exception. + /// + public static async Task> ThrowExactlyAsync(this AsyncFunctionAssertions asyncActionAssertions, string because = "", + params object[] becauseArgs) + where TException : Exception + { + var exceptionAssertions = await asyncActionAssertions.ThrowAsync(because, becauseArgs); + exceptionAssertions.Which.GetType().Should().Be(because, becauseArgs); + return exceptionAssertions; + } + private class AggregateExceptionExtractor : IExtractExceptions { public IEnumerable OfType(Exception actualException) diff --git a/Tests/Shared.Specs/AsyncFunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/AsyncFunctionExceptionAssertionSpecs.cs index 00b2502752..09ed56561e 100644 --- a/Tests/Shared.Specs/AsyncFunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/AsyncFunctionExceptionAssertionSpecs.cs @@ -171,6 +171,64 @@ public async Task When_async_method_does_not_throw_async_exception_and_that_was_ await action.Should().NotThrowAsync(); } + [Fact] + public async Task When_subject_throws_subclass_of_expected_async_exception_it_should_succeed() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + var asyncObject = new AsyncClass(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Func action = async () => await asyncObject.ThrowAsync(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + await action.Should().ThrowAsync("because {0} should do that", "IFoo.Do"); + } + + [Fact] + public async Task When_subject_throws_subclass_of_expected_async_exact_exception_it_should_throw() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + var asyncObject = new AsyncClass(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Func action = async () => await asyncObject.ThrowAsync(); + Func testAction = async () => await action.Should().ThrowExactlyAsync("ABCDE"); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + (await testAction.Should().ThrowAsync()).WithMessage("*ArgumentException*ABCDE*ArgumentNullException*"); + } + + [Fact] + public async Task When_subject_throws_expected_async_exact_exception_it_should_succeed() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + var asyncObject = new AsyncClass(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Func action = async () => await asyncObject.ThrowAsync(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + await action.Should().ThrowExactlyAsync("because {0} should do that", "IFoo.Do"); + } + [Fact] public void When_async_method_throws_exception_and_no_exception_was_expected_it_should_fail() {