From eabbd6ec6e4e9d20e36b6db9187f5a32cabc81b5 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Mon, 15 Oct 2018 20:48:35 +0200 Subject: [PATCH 01/14] Introduce FunctionAssertions --- Src/FluentAssertions/AssertionExtensions.cs | 12 +++++++++++- Tests/Shared.Specs/Shared.Specs.projitems | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Src/FluentAssertions/AssertionExtensions.cs b/Src/FluentAssertions/AssertionExtensions.cs index 2523875328..1105a06ce9 100644 --- a/Src/FluentAssertions/AssertionExtensions.cs +++ b/Src/FluentAssertions/AssertionExtensions.cs @@ -634,7 +634,7 @@ public static ActionAssertions Should(this Action action) /// /// Returns a object that can be used to assert the - /// current . + /// current . /// [Pure] public static AsyncFunctionAssertions Should(this Func action) @@ -642,6 +642,16 @@ public static AsyncFunctionAssertions Should(this Func action) return new AsyncFunctionAssertions(action, extractor); } + /// + /// Returns a object that can be used to assert the + /// current . + /// + [Pure] + public static FunctionAssertions Should(this Func func) + { + return new FunctionAssertions(func, extractor); + } + #if NET45 || NET47 || NETCOREAPP2_0 /// diff --git a/Tests/Shared.Specs/Shared.Specs.projitems b/Tests/Shared.Specs/Shared.Specs.projitems index b45428bb4b..2565bf98d5 100644 --- a/Tests/Shared.Specs/Shared.Specs.projitems +++ b/Tests/Shared.Specs/Shared.Specs.projitems @@ -15,7 +15,7 @@ - + From 6b1ae9cf5611a799921b5c5da8965a4c9ff27d59 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Fri, 19 Oct 2018 21:30:51 +0200 Subject: [PATCH 02/14] Add tests for FunctionAssertion.Throw --- .../Specialized/FunctionAssertions.cs | 244 ++++++++ .../FunctionExceptionAssertionSpecs.cs | 531 ++++++++++++++++++ 2 files changed, 775 insertions(+) create mode 100644 Src/FluentAssertions/Specialized/FunctionAssertions.cs create mode 100644 Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs new file mode 100644 index 0000000000..2bc685f1d3 --- /dev/null +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -0,0 +1,244 @@ +using System; +using System.Diagnostics; +using System.Linq; + +using FluentAssertions.Execution; + +namespace FluentAssertions.Specialized +{ + /// + /// Contains a number of methods to assert that a synchronous function yields the expected result. + /// + [DebuggerNonUserCode] + public class FunctionAssertions + { + private readonly IExtractExceptions extractor; + + public FunctionAssertions(Func subject, IExtractExceptions extractor) + { + this.extractor = extractor; + Subject = subject; + } + + /// + /// Gets the that is being asserted. + /// + public Func Subject { get; } + + /// + /// Asserts that the current throws an exception of type . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public ExceptionAssertions Throw(string because = "", params object[] becauseArgs) + where TException : Exception + { + Exception exception = InvokeSubjectWithInterception(); + return Throw(exception, because, becauseArgs); + } + + ///// + ///// Asserts that the current throws an exception of type . + ///// + ///// + ///// A formatted phrase as is supported by explaining why the assertion + ///// is needed. If the phrase does not start with the word because, it is prepended automatically. + ///// + ///// + ///// Zero or more objects to format using the placeholders in . + ///// + //public async Task> ThrowAsync(string because = "", params object[] becauseArgs) + // where TException : Exception + //{ + // Exception exception = await InvokeSubjectWithInterceptionAsync(); + // return Throw(exception, because, becauseArgs); + //} + + ///// + ///// Asserts that the current does not throw any exception. + ///// + ///// + ///// A formatted phrase as is supported by explaining why the assertion + ///// is needed. If the phrase does not start with the word because, it is prepended automatically. + ///// + ///// + ///// Zero or more objects to format using the placeholders in . + ///// + //public void NotThrow(string because = "", params object[] becauseArgs) + //{ + // try + // { + // Task.Run(Subject).Wait(); + // } + // catch (Exception exception) + // { + // NotThrow(exception, because, becauseArgs); + // } + //} + + ///// + ///// Asserts that the current does not throw any exception. + ///// + ///// + ///// A formatted phrase as is supported by explaining why the assertion + ///// is needed. If the phrase does not start with the word because, it is prepended automatically. + ///// + ///// + ///// Zero or more objects to format using the placeholders in . + ///// + //public async Task NotThrowAsync(string because = "", params object[] becauseArgs) + //{ + // try + // { + // await Task.Run(Subject); + // } + // catch (Exception exception) + // { + // NotThrow(exception, because, becauseArgs); + // } + //} + + ///// + ///// Asserts that the current does not throw an exception of type . + ///// + ///// + ///// A formatted phrase as is supported by explaining why the assertion + ///// is needed. If the phrase does not start with the word because, it is prepended automatically. + ///// + ///// + ///// Zero or more objects to format using the placeholders in . + ///// + //public void NotThrow(string because = "", params object[] becauseArgs) + // where TException : Exception + //{ + // try + // { + // Task.Run(Subject).Wait(); + // } + // catch (Exception exception) + // { + // NotThrow(exception, because, becauseArgs); + // } + //} + + ///// + ///// Asserts that the current does not throw an exception of type . + ///// + ///// + ///// A formatted phrase as is supported by explaining why the assertion + ///// is needed. If the phrase does not start with the word because, it is prepended automatically. + ///// + ///// + ///// Zero or more objects to format using the placeholders in . + ///// + //public async Task NotThrowAsync(string because = "", params object[] becauseArgs) + // where TException : Exception + //{ + // try + // { + // await Task.Run(Subject); + // } + // catch (Exception exception) + // { + // NotThrow(exception, because, becauseArgs); + // } + //} + + //private static void NotThrow(Exception exception, string because, object[] becauseArgs) + //{ + // Exception nonAggregateException = GetFirstNonAggregateException(exception); + + // Execute.Assertion + // .BecauseOf(because, becauseArgs) + // .FailWith("Did not expect any exception{reason}, but found a {0} with message {1}.", + // nonAggregateException.GetType(), nonAggregateException.ToString()); + //} + + //private static void NotThrow(Exception exception, string because, object[] becauseArgs) where TException : Exception + //{ + // Exception nonAggregateException = GetFirstNonAggregateException(exception); + + // if (nonAggregateException != null) + // { + // Execute.Assertion + // .ForCondition(!(nonAggregateException is TException)) + // .BecauseOf(because, becauseArgs) + // .FailWith("Did not expect {0}{reason}, but found one with message {1}.", + // typeof(TException), nonAggregateException.ToString()); + // } + //} + + //private static Exception GetFirstNonAggregateException(Exception exception) + //{ + // Exception nonAggregateException = exception; + // while (nonAggregateException is AggregateException) + // { + // nonAggregateException = nonAggregateException.InnerException; + // } + + // return nonAggregateException; + //} + + private ExceptionAssertions Throw(Exception exception, string because, object[] becauseArgs) + where TException : Exception + { + var exceptions = extractor.OfType(exception); + + Execute.Assertion + .ForCondition(exception != null) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but no exception was thrown.", typeof(TException)); + + Execute.Assertion + .ForCondition(exceptions.Any()) + .BecauseOf(because, becauseArgs) + .FailWith("Expected {0}{reason}, but found {1}.", typeof(TException), exception); + + return new ExceptionAssertions(exceptions); + } + + private Exception InvokeSubjectWithInterception() + { + try + { + Subject(); + } + catch (Exception exception) + { + return InterceptException(exception); + } + + return null; + } + + //private async Task InvokeSubjectWithInterceptionAsync() + //{ + // try + // { + // await Task.Run(Subject); + // } + // catch (Exception exception) + // { + // return InterceptException(exception); + // } + + // return null; + //} + + private Exception InterceptException(Exception exception) + { + var ar = exception as AggregateException; + if (ar?.InnerException is AggregateException) + { + return ar.InnerException; + } + + return exception; + } + } +} diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs new file mode 100644 index 0000000000..265d680b82 --- /dev/null +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -0,0 +1,531 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Xunit; +using Xunit.Sdk; + +namespace FluentAssertions.Specs +{ + public class FunctionExceptionAssertionSpecs + { + [Fact] + public void When_subject_throws_the_expected_exact_exception_it_should_succeed() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act / Assert + //----------------------------------------------------------------------------------------------------------- + f.Should().Throw(); + } + + [Fact] + public void When_subject_does_not_throw_expected_exception_it_should_fail() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().Throw(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("Expected*InvalidCastException*but*ArgumentNullException*"); + } + + [Fact] + public void When_subject_does_not_throw_any_exception_it_should_fail() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => 12; + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().Throw("that's what I {0}", "said"); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("Expected*InvalidCastException*that's what I said*but*no exception*"); + } + + //[Fact] + //public void When_subject_throws_subclass_of_expected_exact_exception_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncObject + // .Awaiting(x => x.ThrowAsync()) + // .Should().ThrowExactly("because {0} should do that", "IFoo.Do"); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw() + // .WithMessage("Expected type to be System.ArgumentException because IFoo.Do should do that, but found System.ArgumentNullException."); + //} + + + //[Fact] + //public async void When_async_method_throws_async_expected_exception_it_should_succeed() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Func action = async () => await asyncObject.ThrowAsync(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // await action.Should().ThrowAsync(); + + //} + + //[Fact] + //public void When_async_method_throws_unexpected_exception_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncObject + // .Awaiting(x => x.ThrowAsync()) + // .Should().Throw("because {0} should do that", "IFoo.Do"); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw() + // .WithMessage("Expected System.InvalidOperationException because IFoo.Do should do that, but found*System.ArgumentException*"); + //} + + //[Fact] + //public void When_async_method_does_not_throw_exception_and_that_was_expected_it_should_succeed() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncObject + // .Awaiting(x => x.SucceedAsync()) + // .Should().NotThrow(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().NotThrow(); + //} + + //[Fact] + //public async Task When_async_method_does_not_throw_async_exception_and_that_was_expected_it_should_succeed() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Func action = async () => await asyncObject.SucceedAsync(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // 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() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncObject + // .Awaiting(x => x.ThrowAsync()) + // .Should().NotThrow(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw() + // .WithMessage("Did not expect any exception, but found a System.ArgumentException*"); + //} + + //[Fact] + //public void When_async_method_throws_exception_and_expected_not_to_throw_another_one_it_should_succeed() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncObject + // .Awaiting(x => x.ThrowAsync()) + // .Should().NotThrow(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().NotThrow(); + //} + + //[Fact] + //public async Task When_async_method_throws_exception_and_expected_not_to_throw_async_another_one_it_should_succeed() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Func action = async () => await asyncObject.ThrowAsync(); + + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // await action.Should().NotThrowAsync(); + //} + + //[Fact] + //public void When_async_method_succeeds_and_expected_not_to_throw_particular_exception_it_should_succeed() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncObject + // .Awaiting(x => asyncObject.SucceedAsync()) + // .Should().NotThrow(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().NotThrow(); + //} + + //[Fact] + //public void When_async_method_throws_exception_expected_not_to_be_thrown_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncObject + // .Awaiting(x => x.ThrowAsync()) + // .Should().NotThrow(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw() + // .WithMessage("Did not expect System.ArgumentException, but found one*"); + //} + + //[Fact] + //public void When_async_method_throws_the_expected_inner_exception_it_should_succeed() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // Func task = async () => + // { + // await Task.Delay(100); + // throw new InvalidOperationException(); + // }; + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => task + // .Should().Throw() + // .WithInnerException(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().NotThrow(); + //} + + //[Fact] + //public void When_async_method_throws_the_expected_exception_it_should_succeed() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // Func task = async () => + // { + // await Task.Delay(100); + // throw new InvalidOperationException(); + // }; + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => task + // .Should().Throw(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().NotThrow(); + //} + + //[Fact] + //public void When_async_method_does_not_throw_the_expected_inner_exception_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // Func task = async () => + // { + // await Task.Delay(100); + // throw new ArgumentException(); + // }; + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => task + // .Should().Throw() + // .WithInnerException(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw().WithMessage("*InvalidOperation*Argument*"); + //} + + //[Fact] + //public void When_async_method_does_not_throw_the_expected_exception_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // Func task = async () => + // { + // await Task.Delay(100); + // throw new ArgumentException(); + // }; + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => task + // .Should().Throw(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw().WithMessage("*InvalidOperation*Argument*"); + //} + + //[Fact] + //public void When_asserting_async_void_method_should_throw_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + // Action asyncVoidMethod = async () => await asyncObject.IncompleteTask(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncVoidMethod.Should().Throw(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw("*async*void*"); + //} + + //[Fact] + //public void When_asserting_async_void_method_should_throw_exactly_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + // Action asyncVoidMethod = async () => await asyncObject.IncompleteTask(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncVoidMethod.Should().ThrowExactly(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw("*async*void*"); + //} + + //[Fact] + //public void When_asserting_async_void_method_should_not_throw_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + // Action asyncVoidMethod = async () => await asyncObject.IncompleteTask(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncVoidMethod.Should().NotThrow(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw("*async*void*"); + //} + + //[Fact] + //public void When_asserting_async_void_method_should_not_throw_specific_exception_it_should_fail() + //{ + // //----------------------------------------------------------------------------------------------------------- + // // Arrange + // //----------------------------------------------------------------------------------------------------------- + // var asyncObject = new AsyncClass(); + // Action asyncVoidMethod = async () => await asyncObject.IncompleteTask(); + + // //----------------------------------------------------------------------------------------------------------- + // // Act + // //----------------------------------------------------------------------------------------------------------- + // Action action = () => asyncVoidMethod.Should().NotThrow(); + + // //----------------------------------------------------------------------------------------------------------- + // // Assert + // //----------------------------------------------------------------------------------------------------------- + // action.Should().Throw("*async*void*"); + //} + } + + internal class TestThrowingClass + { + public async Task ThrowAsync() + where TException : Exception, new() + { + await Task.Factory.StartNew(() => throw new TException()); + } + + public async Task SucceedAsync() + { + await Task.FromResult(0); + } + + public Task IncompleteTask() + { + return new TaskCompletionSource().Task; + } + } +} From 54a17fe687ff2175429110382157292e50c227f8 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Fri, 19 Oct 2018 22:46:27 +0200 Subject: [PATCH 03/14] Add FunctionAssertions.NotThrow --- .../Specialized/FunctionAssertions.cs | 82 ++++++++++--------- .../FunctionExceptionAssertionSpecs.cs | 54 +++++++----- 2 files changed, 78 insertions(+), 58 deletions(-) diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs index 2bc685f1d3..f7d7a7237b 100644 --- a/Src/FluentAssertions/Specialized/FunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -59,27 +59,33 @@ public ExceptionAssertions Throw(string because = "", pa // return Throw(exception, because, becauseArgs); //} - ///// - ///// Asserts that the current does not throw any exception. - ///// - ///// - ///// A formatted phrase as is supported by explaining why the assertion - ///// is needed. If the phrase does not start with the word because, it is prepended automatically. - ///// - ///// - ///// Zero or more objects to format using the placeholders in . - ///// - //public void NotThrow(string because = "", params object[] becauseArgs) - //{ - // try - // { - // Task.Run(Subject).Wait(); - // } - // catch (Exception exception) - // { - // NotThrow(exception, because, becauseArgs); - // } - //} + /// + /// Asserts that the current does not throw any exception. + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public AndWhichConstraint, T> NotThrow(string because = "", params object[] becauseArgs) + { + try + { + T result = Subject(); + return new AndWhichConstraint, T>(this, result); + } + catch (Exception exception) + { + NotThrow(exception, because, becauseArgs); + } + + // Return null is not necessary + // C# compiler just could not induce that NotThrow always throws + // and complained about "not all paths" returning value + return null; + } ///// ///// Asserts that the current does not throw any exception. @@ -149,15 +155,15 @@ public ExceptionAssertions Throw(string because = "", pa // } //} - //private static void NotThrow(Exception exception, string because, object[] becauseArgs) - //{ - // Exception nonAggregateException = GetFirstNonAggregateException(exception); + private static void NotThrow(Exception exception, string because, object[] becauseArgs) + { + Exception nonAggregateException = GetFirstNonAggregateException(exception); - // Execute.Assertion - // .BecauseOf(because, becauseArgs) - // .FailWith("Did not expect any exception{reason}, but found a {0} with message {1}.", - // nonAggregateException.GetType(), nonAggregateException.ToString()); - //} + Execute.Assertion + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect any exception{reason}, but found a {0} with message {1}.", + nonAggregateException.GetType(), nonAggregateException.ToString()); + } //private static void NotThrow(Exception exception, string because, object[] becauseArgs) where TException : Exception //{ @@ -173,16 +179,16 @@ public ExceptionAssertions Throw(string because = "", pa // } //} - //private static Exception GetFirstNonAggregateException(Exception exception) - //{ - // Exception nonAggregateException = exception; - // while (nonAggregateException is AggregateException) - // { - // nonAggregateException = nonAggregateException.InnerException; - // } + private static Exception GetFirstNonAggregateException(Exception exception) + { + Exception nonAggregateException = exception; + while (nonAggregateException is AggregateException) + { + nonAggregateException = nonAggregateException.InnerException; + } - // return nonAggregateException; - //} + return nonAggregateException; + } private ExceptionAssertions Throw(Exception exception, string because, object[] becauseArgs) where TException : Exception diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index 265d680b82..6e4cf8b4ad 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -1,5 +1,4 @@ using System; -using System.Threading; using System.Threading.Tasks; using Xunit; using Xunit.Sdk; @@ -62,6 +61,40 @@ public void When_subject_does_not_throw_any_exception_it_should_fail() .WithMessage("Expected*InvalidCastException*that's what I said*but*no exception*"); } + [Fact] + public void When_subject_does_not_throw_exception_and_that_was_expected_it_should_succeed_then_continue_assertion() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().NotThrow("that's what he {0}", "told me"); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("*no*exception*that's what he told me*but*ArgumentNullException*"); + } + + [Fact] + public void When_subject_does_throw_exception_and_that_was_not_expected_it_should_fail() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => 12; + + //----------------------------------------------------------------------------------------------------------- + // Act / Assert + //----------------------------------------------------------------------------------------------------------- + f.Should().NotThrow().Which.Should().Be(12); + } + //[Fact] //public void When_subject_throws_subclass_of_expected_exact_exception_it_should_fail() //{ @@ -127,26 +160,7 @@ public void When_subject_does_not_throw_any_exception_it_should_fail() // .WithMessage("Expected System.InvalidOperationException because IFoo.Do should do that, but found*System.ArgumentException*"); //} - //[Fact] - //public void When_async_method_does_not_throw_exception_and_that_was_expected_it_should_succeed() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncObject - // .Awaiting(x => x.SucceedAsync()) - // .Should().NotThrow(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().NotThrow(); - //} //[Fact] //public async Task When_async_method_does_not_throw_async_exception_and_that_was_expected_it_should_succeed() From 54ede238d2eb522eb33ec7a6f9856ef0db5a98d0 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Fri, 19 Oct 2018 22:52:44 +0200 Subject: [PATCH 04/14] Re-add AsyncFunctionExceptionAssertionSpecs, they were removed by mistake --- Tests/Shared.Specs/Shared.Specs.projitems | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Shared.Specs/Shared.Specs.projitems b/Tests/Shared.Specs/Shared.Specs.projitems index 2565bf98d5..2f661263d9 100644 --- a/Tests/Shared.Specs/Shared.Specs.projitems +++ b/Tests/Shared.Specs/Shared.Specs.projitems @@ -15,6 +15,7 @@ + From a2533d332fb367c98aa6adf8da0ff35f4933c37e Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Sun, 28 Oct 2018 07:21:43 +0100 Subject: [PATCH 05/14] Minor fixes after code review --- Src/FluentAssertions/Specialized/FunctionAssertions.cs | 10 +++------- Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs | 9 +++++++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs index f7d7a7237b..6a4b9e97ea 100644 --- a/Src/FluentAssertions/Specialized/FunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -79,12 +79,9 @@ public ExceptionAssertions Throw(string because = "", pa catch (Exception exception) { NotThrow(exception, because, becauseArgs); - } + return null; - // Return null is not necessary - // C# compiler just could not induce that NotThrow always throws - // and complained about "not all paths" returning value - return null; + } } ///// @@ -213,13 +210,12 @@ private Exception InvokeSubjectWithInterception() try { Subject(); + return null; } catch (Exception exception) { return InterceptException(exception); } - - return null; } //private async Task InvokeSubjectWithInterceptionAsync() diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index 6e4cf8b4ad..cc1eaae757 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -7,6 +7,7 @@ namespace FluentAssertions.Specs { public class FunctionExceptionAssertionSpecs { + #region Throw [Fact] public void When_subject_throws_the_expected_exact_exception_it_should_succeed() { @@ -62,7 +63,7 @@ public void When_subject_does_not_throw_any_exception_it_should_fail() } [Fact] - public void When_subject_does_not_throw_exception_and_that_was_expected_it_should_succeed_then_continue_assertion() + public void When_subject_throw_exception_and_that_was_not_expected_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -80,9 +81,11 @@ public void When_subject_does_not_throw_exception_and_that_was_expected_it_shoul action.Should().Throw() .WithMessage("*no*exception*that's what he told me*but*ArgumentNullException*"); } + #endregion + #region NotThrow [Fact] - public void When_subject_does_throw_exception_and_that_was_not_expected_it_should_fail() + public void When_subject_does_not_throw_exception_and_that_was_expected_it_should_succeed_then_continue_assertion() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -95,6 +98,8 @@ public void When_subject_does_throw_exception_and_that_was_not_expected_it_shoul f.Should().NotThrow().Which.Should().Be(12); } + #endregion + //[Fact] //public void When_subject_throws_subclass_of_expected_exact_exception_it_should_fail() //{ From d90a47b944ebc0167efb02edfb34a1e9029fcdce Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Sun, 28 Oct 2018 15:36:18 +0100 Subject: [PATCH 06/14] Move NotThrow test to NotThrow region --- .../FunctionExceptionAssertionSpecs.cs | 77 +++++-------------- 1 file changed, 18 insertions(+), 59 deletions(-) diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index cc1eaae757..950d5556dd 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -61,41 +61,42 @@ public void When_subject_does_not_throw_any_exception_it_should_fail() action.Should().Throw() .WithMessage("Expected*InvalidCastException*that's what I said*but*no exception*"); } + + #endregion + #region NotThrow [Fact] - public void When_subject_throw_exception_and_that_was_not_expected_it_should_fail() + public void When_subject_does_not_throw_exception_and_that_was_expected_it_should_succeed_then_continue_assertion() { //----------------------------------------------------------------------------------------------------------- // Arrange //----------------------------------------------------------------------------------------------------------- - Func f = () => throw new ArgumentNullException(); - - //----------------------------------------------------------------------------------------------------------- - // Act - //----------------------------------------------------------------------------------------------------------- - Action action = () => f.Should().NotThrow("that's what he {0}", "told me"); + Func f = () => 12; //----------------------------------------------------------------------------------------------------------- - // Assert + // Act / Assert //----------------------------------------------------------------------------------------------------------- - action.Should().Throw() - .WithMessage("*no*exception*that's what he told me*but*ArgumentNullException*"); + f.Should().NotThrow().Which.Should().Be(12); } - #endregion - #region NotThrow [Fact] - public void When_subject_does_not_throw_exception_and_that_was_expected_it_should_succeed_then_continue_assertion() + public void When_subject_throw_exception_and_that_was_not_expected_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange //----------------------------------------------------------------------------------------------------------- - Func f = () => 12; + Func f = () => throw new ArgumentNullException(); //----------------------------------------------------------------------------------------------------------- - // Act / Assert + // Act //----------------------------------------------------------------------------------------------------------- - f.Should().NotThrow().Which.Should().Be(12); + Action action = () => f.Should().NotThrow("that's what he {0}", "told me"); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("*no*exception*that's what he told me*but*ArgumentNullException*"); } #endregion @@ -164,27 +165,7 @@ public void When_subject_does_not_throw_exception_and_that_was_expected_it_shoul // action.Should().Throw() // .WithMessage("Expected System.InvalidOperationException because IFoo.Do should do that, but found*System.ArgumentException*"); //} - - - - //[Fact] - //public async Task When_async_method_does_not_throw_async_exception_and_that_was_expected_it_should_succeed() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Func action = async () => await asyncObject.SucceedAsync(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // await action.Should().NotThrowAsync(); - //} + //[Fact] //public async Task When_subject_throws_subclass_of_expected_async_exception_it_should_succeed() @@ -244,28 +225,6 @@ public void When_subject_does_not_throw_exception_and_that_was_expected_it_shoul // 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() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncObject - // .Awaiting(x => x.ThrowAsync()) - // .Should().NotThrow(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw() - // .WithMessage("Did not expect any exception, but found a System.ArgumentException*"); - //} - //[Fact] //public void When_async_method_throws_exception_and_expected_not_to_throw_another_one_it_should_succeed() //{ From 90e71aff1de1bfe9e9d8072f662d71350c3b9b5a Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Sun, 28 Oct 2018 15:44:43 +0100 Subject: [PATCH 07/14] Add one more positive test for Throw --- .../FunctionExceptionAssertionSpecs.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index 950d5556dd..5bd0d3f703 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -22,6 +22,20 @@ public void When_subject_throws_the_expected_exact_exception_it_should_succeed() f.Should().Throw(); } + [Fact] + public void When_subject_throws_the_expected_exception_it_should_succeed() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act / Assert + //----------------------------------------------------------------------------------------------------------- + f.Should().Throw(); + } + [Fact] public void When_subject_does_not_throw_expected_exception_it_should_fail() { From b423a8c95164e4fe1848bc24a221af80c1a73336 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Sun, 28 Oct 2018 16:09:29 +0100 Subject: [PATCH 08/14] Add FunctionAssertions.NotThrow --- .../Specialized/FunctionAssertions.cs | 130 +++++------------- .../FunctionExceptionAssertionSpecs.cs | 59 +++++++- 2 files changed, 92 insertions(+), 97 deletions(-) diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs index 6a4b9e97ea..1ac1d828ac 100644 --- a/Src/FluentAssertions/Specialized/FunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -42,23 +42,6 @@ public ExceptionAssertions Throw(string because = "", pa return Throw(exception, because, becauseArgs); } - ///// - ///// Asserts that the current throws an exception of type . - ///// - ///// - ///// A formatted phrase as is supported by explaining why the assertion - ///// is needed. If the phrase does not start with the word because, it is prepended automatically. - ///// - ///// - ///// Zero or more objects to format using the placeholders in . - ///// - //public async Task> ThrowAsync(string because = "", params object[] becauseArgs) - // where TException : Exception - //{ - // Exception exception = await InvokeSubjectWithInterceptionAsync(); - // return Throw(exception, because, becauseArgs); - //} - /// /// Asserts that the current does not throw any exception. /// @@ -84,73 +67,28 @@ public ExceptionAssertions Throw(string because = "", pa } } - ///// - ///// Asserts that the current does not throw any exception. - ///// - ///// - ///// A formatted phrase as is supported by explaining why the assertion - ///// is needed. If the phrase does not start with the word because, it is prepended automatically. - ///// - ///// - ///// Zero or more objects to format using the placeholders in . - ///// - //public async Task NotThrowAsync(string because = "", params object[] becauseArgs) - //{ - // try - // { - // await Task.Run(Subject); - // } - // catch (Exception exception) - // { - // NotThrow(exception, because, becauseArgs); - // } - //} - - ///// - ///// Asserts that the current does not throw an exception of type . - ///// - ///// - ///// A formatted phrase as is supported by explaining why the assertion - ///// is needed. If the phrase does not start with the word because, it is prepended automatically. - ///// - ///// - ///// Zero or more objects to format using the placeholders in . - ///// - //public void NotThrow(string because = "", params object[] becauseArgs) - // where TException : Exception - //{ - // try - // { - // Task.Run(Subject).Wait(); - // } - // catch (Exception exception) - // { - // NotThrow(exception, because, becauseArgs); - // } - //} - - ///// - ///// Asserts that the current does not throw an exception of type . - ///// - ///// - ///// A formatted phrase as is supported by explaining why the assertion - ///// is needed. If the phrase does not start with the word because, it is prepended automatically. - ///// - ///// - ///// Zero or more objects to format using the placeholders in . - ///// - //public async Task NotThrowAsync(string because = "", params object[] becauseArgs) - // where TException : Exception - //{ - // try - // { - // await Task.Run(Subject); - // } - // catch (Exception exception) - // { - // NotThrow(exception, because, becauseArgs); - // } - //} + /// + /// Asserts that the current does not throw an exception of type . + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public void NotThrow(string because = "", params object[] becauseArgs) + where TException : Exception + { + try + { + Subject(); + } + catch (Exception exception) + { + NotThrow(exception, because, becauseArgs); + } + } private static void NotThrow(Exception exception, string because, object[] becauseArgs) { @@ -162,19 +100,19 @@ private static void NotThrow(Exception exception, string because, object[] becau nonAggregateException.GetType(), nonAggregateException.ToString()); } - //private static void NotThrow(Exception exception, string because, object[] becauseArgs) where TException : Exception - //{ - // Exception nonAggregateException = GetFirstNonAggregateException(exception); + private static void NotThrow(Exception exception, string because, object[] becauseArgs) where TException : Exception + { + Exception nonAggregateException = GetFirstNonAggregateException(exception); - // if (nonAggregateException != null) - // { - // Execute.Assertion - // .ForCondition(!(nonAggregateException is TException)) - // .BecauseOf(because, becauseArgs) - // .FailWith("Did not expect {0}{reason}, but found one with message {1}.", - // typeof(TException), nonAggregateException.ToString()); - // } - //} + if (nonAggregateException != null) + { + Execute.Assertion + .ForCondition(!(nonAggregateException is TException)) + .BecauseOf(because, becauseArgs) + .FailWith("Did not expect {0}{reason}, but found one with message {1}.", + typeof(TException), nonAggregateException.ToString()); + } + } private static Exception GetFirstNonAggregateException(Exception exception) { diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index 5bd0d3f703..294009b0ac 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -115,6 +115,63 @@ public void When_subject_throw_exception_and_that_was_not_expected_it_should_fai #endregion + #region NotThrow + [Fact] + public void When_subject_does_not_throw_at_all_when_some_particular_exception_was_not_expected_it_should_succeed_but_then_cannot_continue_assertion() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => 12; + + //----------------------------------------------------------------------------------------------------------- + // Act / Assert + //----------------------------------------------------------------------------------------------------------- + f.Should().NotThrow(); + //.Which.Should().Be(12); <- this is invalid, because NotThrow does not guarantee that no exception was thrown. + } + + [Fact] + public void When_subject_does_throw_exception_and_that_exception_was_not_expected_it_should_fail() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new InvalidOperationException("custom message"); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().NotThrow("it was so {0}", "fast"); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("*Did not expect System.InvalidOperationException because it was so fast, but found one with message*custom message*"); + } + + [Fact] + public void When_subject_throw_one_exception_but_other_was_not_expected_it_should_succeed() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().NotThrow(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().NotThrow(); + } + + #endregion + //[Fact] //public void When_subject_throws_subclass_of_expected_exact_exception_it_should_fail() //{ @@ -179,7 +236,7 @@ public void When_subject_throw_exception_and_that_was_not_expected_it_should_fai // action.Should().Throw() // .WithMessage("Expected System.InvalidOperationException because IFoo.Do should do that, but found*System.ArgumentException*"); //} - + //[Fact] //public async Task When_subject_throws_subclass_of_expected_async_exception_it_should_succeed() From 442c277ea11e00fe6888b9d7effaa82dbb843921 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Sun, 28 Oct 2018 16:15:04 +0100 Subject: [PATCH 09/14] Remove commented out async tests --- .../FunctionExceptionAssertionSpecs.cs | 405 ------------------ 1 file changed, 405 deletions(-) diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index 294009b0ac..8a143a716a 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -171,410 +171,5 @@ public void When_subject_throw_one_exception_but_other_was_not_expected_it_shoul } #endregion - - //[Fact] - //public void When_subject_throws_subclass_of_expected_exact_exception_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncObject - // .Awaiting(x => x.ThrowAsync()) - // .Should().ThrowExactly("because {0} should do that", "IFoo.Do"); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw() - // .WithMessage("Expected type to be System.ArgumentException because IFoo.Do should do that, but found System.ArgumentNullException."); - //} - - - //[Fact] - //public async void When_async_method_throws_async_expected_exception_it_should_succeed() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Func action = async () => await asyncObject.ThrowAsync(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // await action.Should().ThrowAsync(); - - //} - - //[Fact] - //public void When_async_method_throws_unexpected_exception_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncObject - // .Awaiting(x => x.ThrowAsync()) - // .Should().Throw("because {0} should do that", "IFoo.Do"); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw() - // .WithMessage("Expected System.InvalidOperationException because IFoo.Do should do that, but found*System.ArgumentException*"); - //} - - - //[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_expected_not_to_throw_another_one_it_should_succeed() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncObject - // .Awaiting(x => x.ThrowAsync()) - // .Should().NotThrow(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().NotThrow(); - //} - - //[Fact] - //public async Task When_async_method_throws_exception_and_expected_not_to_throw_async_another_one_it_should_succeed() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Func action = async () => await asyncObject.ThrowAsync(); - - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // await action.Should().NotThrowAsync(); - //} - - //[Fact] - //public void When_async_method_succeeds_and_expected_not_to_throw_particular_exception_it_should_succeed() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncObject - // .Awaiting(x => asyncObject.SucceedAsync()) - // .Should().NotThrow(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().NotThrow(); - //} - - //[Fact] - //public void When_async_method_throws_exception_expected_not_to_be_thrown_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncObject - // .Awaiting(x => x.ThrowAsync()) - // .Should().NotThrow(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw() - // .WithMessage("Did not expect System.ArgumentException, but found one*"); - //} - - //[Fact] - //public void When_async_method_throws_the_expected_inner_exception_it_should_succeed() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // Func task = async () => - // { - // await Task.Delay(100); - // throw new InvalidOperationException(); - // }; - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => task - // .Should().Throw() - // .WithInnerException(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().NotThrow(); - //} - - //[Fact] - //public void When_async_method_throws_the_expected_exception_it_should_succeed() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // Func task = async () => - // { - // await Task.Delay(100); - // throw new InvalidOperationException(); - // }; - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => task - // .Should().Throw(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().NotThrow(); - //} - - //[Fact] - //public void When_async_method_does_not_throw_the_expected_inner_exception_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // Func task = async () => - // { - // await Task.Delay(100); - // throw new ArgumentException(); - // }; - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => task - // .Should().Throw() - // .WithInnerException(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw().WithMessage("*InvalidOperation*Argument*"); - //} - - //[Fact] - //public void When_async_method_does_not_throw_the_expected_exception_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // Func task = async () => - // { - // await Task.Delay(100); - // throw new ArgumentException(); - // }; - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => task - // .Should().Throw(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw().WithMessage("*InvalidOperation*Argument*"); - //} - - //[Fact] - //public void When_asserting_async_void_method_should_throw_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - // Action asyncVoidMethod = async () => await asyncObject.IncompleteTask(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncVoidMethod.Should().Throw(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw("*async*void*"); - //} - - //[Fact] - //public void When_asserting_async_void_method_should_throw_exactly_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - // Action asyncVoidMethod = async () => await asyncObject.IncompleteTask(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncVoidMethod.Should().ThrowExactly(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw("*async*void*"); - //} - - //[Fact] - //public void When_asserting_async_void_method_should_not_throw_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - // Action asyncVoidMethod = async () => await asyncObject.IncompleteTask(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncVoidMethod.Should().NotThrow(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw("*async*void*"); - //} - - //[Fact] - //public void When_asserting_async_void_method_should_not_throw_specific_exception_it_should_fail() - //{ - // //----------------------------------------------------------------------------------------------------------- - // // Arrange - // //----------------------------------------------------------------------------------------------------------- - // var asyncObject = new AsyncClass(); - // Action asyncVoidMethod = async () => await asyncObject.IncompleteTask(); - - // //----------------------------------------------------------------------------------------------------------- - // // Act - // //----------------------------------------------------------------------------------------------------------- - // Action action = () => asyncVoidMethod.Should().NotThrow(); - - // //----------------------------------------------------------------------------------------------------------- - // // Assert - // //----------------------------------------------------------------------------------------------------------- - // action.Should().Throw("*async*void*"); - //} - } - - internal class TestThrowingClass - { - public async Task ThrowAsync() - where TException : Exception, new() - { - await Task.Factory.StartNew(() => throw new TException()); - } - - public async Task SucceedAsync() - { - await Task.FromResult(0); - } - - public Task IncompleteTask() - { - return new TaskCompletionSource().Task; - } } } From 5fbdd88d1eae44f482c52b1a0904b0f6b14a93f5 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Sun, 28 Oct 2018 22:05:45 +0100 Subject: [PATCH 10/14] Add FunctionAssertions.ThrowExactly --- .../Specialized/FunctionAssertions.cs | 32 +++---- .../FunctionExceptionAssertionSpecs.cs | 84 ++++++++++++++++++- 2 files changed, 98 insertions(+), 18 deletions(-) diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs index 1ac1d828ac..f3227552a1 100644 --- a/Src/FluentAssertions/Specialized/FunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -42,6 +42,24 @@ public ExceptionAssertions Throw(string because = "", pa return Throw(exception, because, becauseArgs); } + /// + /// Asserts that the current throws an exception of the exact type (and not a derived exception type). + /// + /// + /// A formatted phrase as is supported by explaining why the assertion + /// is needed. If the phrase does not start with the word because, it is prepended automatically. + /// + /// + /// Zero or more objects to format using the placeholders in . + /// + public ExceptionAssertions ThrowExactly(string because = "", params object[] becauseArgs) + where TException : Exception + { + var exceptionAssertions = Throw(because, becauseArgs); + exceptionAssertions.Which.GetType().Should().Be(because, becauseArgs); + return exceptionAssertions; + } + /// /// Asserts that the current does not throw any exception. /// @@ -156,20 +174,6 @@ private Exception InvokeSubjectWithInterception() } } - //private async Task InvokeSubjectWithInterceptionAsync() - //{ - // try - // { - // await Task.Run(Subject); - // } - // catch (Exception exception) - // { - // return InterceptException(exception); - // } - - // return null; - //} - private Exception InterceptException(Exception exception) { var ar = exception as AggregateException; diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index 8a143a716a..451910c981 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -1,5 +1,4 @@ using System; -using System.Threading.Tasks; using Xunit; using Xunit.Sdk; @@ -9,7 +8,7 @@ public class FunctionExceptionAssertionSpecs { #region Throw [Fact] - public void When_subject_throws_the_expected_exact_exception_it_should_succeed() + public void When_subject_throws_the_expected_exception_it_should_succeed() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -23,7 +22,7 @@ public void When_subject_throws_the_expected_exact_exception_it_should_succeed() } [Fact] - public void When_subject_throws_the_expected_exception_it_should_succeed() + public void When_subject_throws_subclass_of_the_expected_exception_it_should_succeed() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -75,7 +74,84 @@ public void When_subject_does_not_throw_any_exception_it_should_fail() action.Should().Throw() .WithMessage("Expected*InvalidCastException*that's what I said*but*no exception*"); } - + + #endregion + + #region ThrowExactly + [Fact] + public void When_subject_throws_the_expected_exact_exception_it_should_succeed() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act / Assert + //----------------------------------------------------------------------------------------------------------- + f.Should().ThrowExactly(); + } + + [Fact] + public void When_subject_throws_subclass_of_the_expected_exact_exception_it_should_fail() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().ThrowExactly(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("Expected*ArgumentException*but*ArgumentNullException*"); + } + + [Fact] + public void When_subject_does_not_throw_expected_exact_exception_it_should_fail() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().ThrowExactly(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("Expected*InvalidCastException*but*ArgumentNullException*"); + } + + [Fact] + public void When_subject_does_not_throw_any_exception_when_expected_exact_it_should_fail() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => 12; + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().ThrowExactly("that's what I {0}", "said"); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("Expected*InvalidCastException*that's what I said*but*no exception*"); + } + #endregion #region NotThrow From a64ca34ec06079abf326358836d7e2a4e39daeaa Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Mon, 29 Oct 2018 07:44:05 +0100 Subject: [PATCH 11/14] Check exception != null before passing to exceptions extractor --- Src/FluentAssertions/Specialized/FunctionAssertions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs index f3227552a1..c67fa175e1 100644 --- a/Src/FluentAssertions/Specialized/FunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -146,13 +146,13 @@ private static Exception GetFirstNonAggregateException(Exception exception) private ExceptionAssertions Throw(Exception exception, string because, object[] becauseArgs) where TException : Exception { - var exceptions = extractor.OfType(exception); - Execute.Assertion .ForCondition(exception != null) .BecauseOf(because, becauseArgs) .FailWith("Expected {0}{reason}, but no exception was thrown.", typeof(TException)); + var exceptions = extractor.OfType(exception); + Execute.Assertion .ForCondition(exceptions.Any()) .BecauseOf(because, becauseArgs) From 53cebe8e7c889fa75038a62b04e0b8fe1a3205ef Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Mon, 29 Oct 2018 22:24:48 +0100 Subject: [PATCH 12/14] Add tests for extracting inner exceptions for aggregate exceptions --- .../Specialized/FunctionAssertions.cs | 15 +-- .../FunctionExceptionAssertionSpecs.cs | 118 ++++++++++++++++++ 2 files changed, 120 insertions(+), 13 deletions(-) diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs index c67fa175e1..155386dff1 100644 --- a/Src/FluentAssertions/Specialized/FunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -9,7 +9,7 @@ namespace FluentAssertions.Specialized /// /// Contains a number of methods to assert that a synchronous function yields the expected result. /// - [DebuggerNonUserCode] + //[DebuggerNonUserCode] public class FunctionAssertions { private readonly IExtractExceptions extractor; @@ -170,19 +170,8 @@ private Exception InvokeSubjectWithInterception() } catch (Exception exception) { - return InterceptException(exception); + return exception; } } - - private Exception InterceptException(Exception exception) - { - var ar = exception as AggregateException; - if (ar?.InnerException is AggregateException) - { - return ar.InnerException; - } - - return exception; - } } } diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index 451910c981..344cdfeb6a 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -55,6 +55,84 @@ public void When_subject_does_not_throw_expected_exception_it_should_fail() .WithMessage("Expected*InvalidCastException*but*ArgumentNullException*"); } + [Fact] + public void When_subject_does_not_throw_expected_exception_but_throws_aggregate_it_should_fail_with_inner_exception() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new AggregateException(new ArgumentNullException()); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().Throw(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("Expected*InvalidCastException*but*ArgumentNullException*"); + } + + [Fact] + public void When_subject_does_throw_expected_exception_but_in_aggregate_it_should_succeed() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new AggregateException(new ArgumentNullException()); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().Throw(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().NotThrow(); + } + + [Fact] + public void When_subject_does_not_throw_expected_exception_but_throws_aggregate_in_aggregate_it_should_fail_with_inner_exception_one_level_deep() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new AggregateException(new AggregateException(new ArgumentNullException())); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().Throw(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("Expected*InvalidCastException*but*ArgumentNullException*"); + } + + [Fact] + public void When_subject_does_throw_expected_exception_but_in_aggregate_in_aggregate_it_should_succeed() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new AggregateException(new AggregateException(new ArgumentNullException())); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().Throw(); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().NotThrow(); + } + [Fact] public void When_subject_does_not_throw_any_exception_it_should_fail() { @@ -189,6 +267,46 @@ public void When_subject_throw_exception_and_that_was_not_expected_it_should_fai .WithMessage("*no*exception*that's what he told me*but*ArgumentNullException*"); } + [Fact] + public void When_subject_throw_aggregate_exception_and_that_was_not_expected_it_should_fail_with_inner_exception_in_message() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new AggregateException(new ArgumentNullException()); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().NotThrow("that's what he {0}", "told me"); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("*no*exception*that's what he told me*but*ArgumentNullException*"); + } + + [Fact] + public void When_subject_throw_aggregate_in_aggregate_exception_and_that_was_not_expected_it_should_fail_with_most_inner_exception_in_message() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new AggregateException(new AggregateException(new ArgumentNullException())); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Action action = () => f.Should().NotThrow("that's what he {0}", "told me"); + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + action.Should().Throw() + .WithMessage("*no*exception*that's what he told me*but*ArgumentNullException*"); + } + #endregion #region NotThrow From 2e2ea5aa7ea8a11842fb06766c1b33572041c889 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Wed, 31 Oct 2018 20:21:39 +0100 Subject: [PATCH 13/14] When_subject to When_function --- .../Specialized/FunctionAssertions.cs | 2 +- .../FunctionExceptionAssertionSpecs.cs | 38 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs index 155386dff1..0dd79b6f0f 100644 --- a/Src/FluentAssertions/Specialized/FunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -9,7 +9,7 @@ namespace FluentAssertions.Specialized /// /// Contains a number of methods to assert that a synchronous function yields the expected result. /// - //[DebuggerNonUserCode] + [DebuggerNonUserCode] public class FunctionAssertions { private readonly IExtractExceptions extractor; diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index 344cdfeb6a..cf7c78f04d 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -8,7 +8,7 @@ public class FunctionExceptionAssertionSpecs { #region Throw [Fact] - public void When_subject_throws_the_expected_exception_it_should_succeed() + public void When_function_throws_the_expected_exception_it_should_succeed() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -22,7 +22,7 @@ public void When_subject_throws_the_expected_exception_it_should_succeed() } [Fact] - public void When_subject_throws_subclass_of_the_expected_exception_it_should_succeed() + public void When_function_throws_subclass_of_the_expected_exception_it_should_succeed() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -36,7 +36,7 @@ public void When_subject_throws_subclass_of_the_expected_exception_it_should_suc } [Fact] - public void When_subject_does_not_throw_expected_exception_it_should_fail() + public void When_function_does_not_throw_expected_exception_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -56,7 +56,7 @@ public void When_subject_does_not_throw_expected_exception_it_should_fail() } [Fact] - public void When_subject_does_not_throw_expected_exception_but_throws_aggregate_it_should_fail_with_inner_exception() + public void When_function_does_not_throw_expected_exception_but_throws_aggregate_it_should_fail_with_inner_exception() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -76,7 +76,7 @@ public void When_subject_does_not_throw_expected_exception_but_throws_aggregate_ } [Fact] - public void When_subject_does_throw_expected_exception_but_in_aggregate_it_should_succeed() + public void When_function_does_throw_expected_exception_but_in_aggregate_it_should_succeed() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -95,7 +95,7 @@ public void When_subject_does_throw_expected_exception_but_in_aggregate_it_shoul } [Fact] - public void When_subject_does_not_throw_expected_exception_but_throws_aggregate_in_aggregate_it_should_fail_with_inner_exception_one_level_deep() + public void When_function_does_not_throw_expected_exception_but_throws_aggregate_in_aggregate_it_should_fail_with_inner_exception_one_level_deep() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -115,7 +115,7 @@ public void When_subject_does_not_throw_expected_exception_but_throws_aggregate_ } [Fact] - public void When_subject_does_throw_expected_exception_but_in_aggregate_in_aggregate_it_should_succeed() + public void When_function_does_throw_expected_exception_but_in_aggregate_in_aggregate_it_should_succeed() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -134,7 +134,7 @@ public void When_subject_does_throw_expected_exception_but_in_aggregate_in_aggre } [Fact] - public void When_subject_does_not_throw_any_exception_it_should_fail() + public void When_function_does_not_throw_any_exception_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -157,7 +157,7 @@ public void When_subject_does_not_throw_any_exception_it_should_fail() #region ThrowExactly [Fact] - public void When_subject_throws_the_expected_exact_exception_it_should_succeed() + public void When_function_throws_the_expected_exact_exception_it_should_succeed() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -171,7 +171,7 @@ public void When_subject_throws_the_expected_exact_exception_it_should_succeed() } [Fact] - public void When_subject_throws_subclass_of_the_expected_exact_exception_it_should_fail() + public void When_function_throws_subclass_of_the_expected_exact_exception_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -191,7 +191,7 @@ public void When_subject_throws_subclass_of_the_expected_exact_exception_it_shou } [Fact] - public void When_subject_does_not_throw_expected_exact_exception_it_should_fail() + public void When_function_does_not_throw_expected_exact_exception_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -211,7 +211,7 @@ public void When_subject_does_not_throw_expected_exact_exception_it_should_fail( } [Fact] - public void When_subject_does_not_throw_any_exception_when_expected_exact_it_should_fail() + public void When_function_does_not_throw_any_exception_when_expected_exact_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -234,7 +234,7 @@ public void When_subject_does_not_throw_any_exception_when_expected_exact_it_sho #region NotThrow [Fact] - public void When_subject_does_not_throw_exception_and_that_was_expected_it_should_succeed_then_continue_assertion() + public void When_function_does_not_throw_exception_and_that_was_expected_it_should_succeed_then_continue_assertion() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -248,7 +248,7 @@ public void When_subject_does_not_throw_exception_and_that_was_expected_it_shoul } [Fact] - public void When_subject_throw_exception_and_that_was_not_expected_it_should_fail() + public void When_function_throw_exception_and_that_was_not_expected_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -268,7 +268,7 @@ public void When_subject_throw_exception_and_that_was_not_expected_it_should_fai } [Fact] - public void When_subject_throw_aggregate_exception_and_that_was_not_expected_it_should_fail_with_inner_exception_in_message() + public void When_function_throw_aggregate_exception_and_that_was_not_expected_it_should_fail_with_inner_exception_in_message() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -288,7 +288,7 @@ public void When_subject_throw_aggregate_exception_and_that_was_not_expected_it_ } [Fact] - public void When_subject_throw_aggregate_in_aggregate_exception_and_that_was_not_expected_it_should_fail_with_most_inner_exception_in_message() + public void When_function_throw_aggregate_in_aggregate_exception_and_that_was_not_expected_it_should_fail_with_most_inner_exception_in_message() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -311,7 +311,7 @@ public void When_subject_throw_aggregate_in_aggregate_exception_and_that_was_not #region NotThrow [Fact] - public void When_subject_does_not_throw_at_all_when_some_particular_exception_was_not_expected_it_should_succeed_but_then_cannot_continue_assertion() + public void When_function_does_not_throw_at_all_when_some_particular_exception_was_not_expected_it_should_succeed_but_then_cannot_continue_assertion() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -326,7 +326,7 @@ public void When_subject_does_not_throw_at_all_when_some_particular_exception_wa } [Fact] - public void When_subject_does_throw_exception_and_that_exception_was_not_expected_it_should_fail() + public void When_function_does_throw_exception_and_that_exception_was_not_expected_it_should_fail() { //----------------------------------------------------------------------------------------------------------- // Arrange @@ -346,7 +346,7 @@ public void When_subject_does_throw_exception_and_that_exception_was_not_expecte } [Fact] - public void When_subject_throw_one_exception_but_other_was_not_expected_it_should_succeed() + public void When_function_throw_one_exception_but_other_was_not_expected_it_should_succeed() { //----------------------------------------------------------------------------------------------------------- // Arrange From 2ba52f34ee6d27e62320e713fcb07d79a79130b4 Mon Sep 17 00:00:00 2001 From: Artur Krajewski Date: Wed, 31 Oct 2018 20:27:07 +0100 Subject: [PATCH 14/14] FunctionAssertions inherits ReferenceTypeAssertions and test for Subject --- .../Specialized/FunctionAssertions.cs | 8 +++----- .../FunctionExceptionAssertionSpecs.cs | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Src/FluentAssertions/Specialized/FunctionAssertions.cs b/Src/FluentAssertions/Specialized/FunctionAssertions.cs index 0dd79b6f0f..248dc1eaca 100644 --- a/Src/FluentAssertions/Specialized/FunctionAssertions.cs +++ b/Src/FluentAssertions/Specialized/FunctionAssertions.cs @@ -3,6 +3,7 @@ using System.Linq; using FluentAssertions.Execution; +using FluentAssertions.Primitives; namespace FluentAssertions.Specialized { @@ -10,7 +11,7 @@ namespace FluentAssertions.Specialized /// Contains a number of methods to assert that a synchronous function yields the expected result. /// [DebuggerNonUserCode] - public class FunctionAssertions + public class FunctionAssertions : ReferenceTypeAssertions, FunctionAssertions> { private readonly IExtractExceptions extractor; @@ -20,10 +21,7 @@ public FunctionAssertions(Func subject, IExtractExceptions extractor) Subject = subject; } - /// - /// Gets the that is being asserted. - /// - public Func Subject { get; } + protected override string Identifier => "function"; /// /// Asserts that the current throws an exception of type . diff --git a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs index cf7c78f04d..d3f31eca32 100644 --- a/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs +++ b/Tests/Shared.Specs/FunctionExceptionAssertionSpecs.cs @@ -6,6 +6,25 @@ namespace FluentAssertions.Specs { public class FunctionExceptionAssertionSpecs { + [Fact] + public void Function_Assertions_should_expose_subject() + { + //----------------------------------------------------------------------------------------------------------- + // Arrange + //----------------------------------------------------------------------------------------------------------- + Func f = () => throw new ArgumentNullException(); + + //----------------------------------------------------------------------------------------------------------- + // Act + //----------------------------------------------------------------------------------------------------------- + Func subject = f.Should().Subject; + + //----------------------------------------------------------------------------------------------------------- + // Assert + //----------------------------------------------------------------------------------------------------------- + subject.Should().BeSameAs(f); + } + #region Throw [Fact] public void When_function_throws_the_expected_exception_it_should_succeed()