Skip to content

Throw<TException>, NotThrow, NotThrow<TException> and NotThrowAfter are throwing redundant AggregateExceptions #1037

@davidomid

Description

@davidomid

Resolved in PR #1038

Description

This is a minor issue but tasks being called synchronously with .Wait() will throw AggregateExceptions. This means that certain FluentAssertions methods are throwing AggregateExceptions, when they should only be throwing the inner exception.

Example

Take the following test case:

E.g.

public void When_async_method_throws_the_expected_inner_exception_it_should_succeed()
        {
            //-----------------------------------------------------------------------------------------------------------
            // Arrange
            //-----------------------------------------------------------------------------------------------------------
            Func<Task> task = async () =>
            {
                await Task.Delay(100);
                throw new InvalidOperationException();
            };

            //-----------------------------------------------------------------------------------------------------------
            // Act
            //-----------------------------------------------------------------------------------------------------------
            Action action = () => task
                .Should().Throw<AggregateException>()
                .WithInnerException<InvalidOperationException>();

            //-----------------------------------------------------------------------------------------------------------
            // Assert
            //-----------------------------------------------------------------------------------------------------------
            action.Should().NotThrow();
        }

Expected behavior:

I would expect this test to fail, given that the task doesn't throw an AggregateException and instead explicitly just throws an InvalidOperationException.

Actual behavior:

The test passes, because currently certain methods are executing the task synchronously using .Wait(), so if it throws an exception it will wrap it in an AggregateException,

The methods which do this are:

  • public ExceptionAssertions<TException> Throw<TException>(string because = "", params object[] becauseArgs) where TException : Exception

  • public void NotThrowAfter(TimeSpan waitTime, TimeSpan pollInterval, string because = "", params object[] becauseArgs)

  • public void NotThrow(string because = "", params object[] becauseArgs)

  • public void NotThrow<TException>(string because = "", params object[] becauseArgs) where TException : Exception

Proposal

What I propose is replacing all calls to .Wait(), with .GetAwaiter().GetResult().
This should make sure only the top exception is thrown. If the given task does in fact throw an AggregateException, it will still work in the same way. The only difference is that Fluent Assertions itself does not throw AggregateExceptions internally, unnecessarily.

This would require changing 2 tests which, like the one shown above, expect an AggregateException to be thrown with an inner exception. The tests would be modified so the given tasks explicitly throws an AggregateException.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions