-
Notifications
You must be signed in to change notification settings - Fork 731
Improved Stack Trace for Collection Comparison #1615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved Stack Trace for Collection Comparison #1615
Conversation
jnyrup
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the record, here's a dump of how this PR changes the stack trace.
act.Should().Throw<NotImplementedException>()
.Which.StackTrace.Should().Contain("ExceptionThrowingProperty");System.NotImplementedException: The method or operation is not implemented.
at FluentAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) in C:\dev\fluentassertions\Src\FluentAssertions\Equivalency\Steps\GenericEnumerableEquivalencyStep.cs:line 52
at FluentAssertions.Equivalency.EquivalencyValidator.RunStepsUntilEquivalencyIsProven(Comparands comparands, IEquivalencyValidationContext context) in C:\dev\fluentassertions\Src\FluentAssertions\Equivalency\EquivalencyValidator.cs:line 65
at FluentAssertions.Equivalency.EquivalencyValidator.RecursivelyAssertEquality(Comparands comparands, IEquivalencyValidationContext context) in C:\dev\fluentassertions\Src\FluentAssertions\Equivalency\EquivalencyValidator.cs:line 37
at FluentAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands comparands, EquivalencyValidationContext context) in C:\dev\fluentassertions\Src\FluentAssertions\Equivalency\EquivalencyValidator.cs:line 19
at FluentAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1 expectation, Func`2 config, String because, Object[] becauseArgs) in C:\dev\fluentassertions\Src\FluentAssertions\Collections\GenericCollectionAssertions.cs:line 333
at FluentAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1 expectation, String because, Object[] becauseArgs) in C:\dev\fluentassertions\Src\FluentAssertions\Collections\GenericCollectionAssertions.cs:line 284
at FluentAssertions.Specs.Equivalency.CollectionEquivalencySpecs.<>c__DisplayClass113_0.<When_an_exception_is_thrown_during_data_access_the_stack_trace_contains_the_original_site>b__0() in C:\dev\fluentassertions\Tests\FluentAssertions.Specs\Equivalency\CollectionEquivalencySpecs.cs:line 2813
at FluentAssertions.Specs.Equivalency.CollectionEquivalencySpecs.When_an_exception_is_thrown_during_data_access_the_stack_trace_contains_the_original_site() in C:\dev\fluentassertions\Tests\FluentAssertions.Specs\Equivalency\CollectionEquivalencySpecs.cs:line 2817
Notice the second line not present in the trace above.
System.NotImplementedException: The method or operation is not implemented.
at FluentAssertions.Specs.Equivalency.CollectionEquivalencySpecs.ExceptionThrowingClass.get_ExceptionThrowingProperty() in C:\dev\fluentassertions\Tests\FluentAssertions.Specs\Equivalency\CollectionEquivalencySpecs.cs:line 196
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at FluentAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) in C:\dev\fluentassertions\Src\FluentAssertions\Equivalency\Steps\GenericEnumerableEquivalencyStep.cs:line 52
at FluentAssertions.Equivalency.EquivalencyValidator.RunStepsUntilEquivalencyIsProven(Comparands comparands, IEquivalencyValidationContext context) in C:\dev\fluentassertions\Src\FluentAssertions\Equivalency\EquivalencyValidator.cs:line 65
at FluentAssertions.Equivalency.EquivalencyValidator.RecursivelyAssertEquality(Comparands comparands, IEquivalencyValidationContext context) in C:\dev\fluentassertions\Src\FluentAssertions\Equivalency\EquivalencyValidator.cs:line 37
at FluentAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands comparands, EquivalencyValidationContext context) in C:\dev\fluentassertions\Src\FluentAssertions\Equivalency\EquivalencyValidator.cs:line 19
at FluentAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1 expectation, Func`2 config, String because, Object[] becauseArgs) in C:\dev\fluentassertions\Src\FluentAssertions\Collections\GenericCollectionAssertions.cs:line 333
at FluentAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1 expectation, String because, Object[] becauseArgs) in C:\dev\fluentassertions\Src\FluentAssertions\Collections\GenericCollectionAssertions.cs:line 284
at FluentAssertions.Specs.Equivalency.CollectionEquivalencySpecs.<>c__DisplayClass113_0.<When_an_exception_is_thrown_during_data_access_the_stack_trace_contains_the_original_site>b__0() in C:\dev\fluentassertions\Tests\FluentAssertions.Specs\Equivalency\CollectionEquivalencySpecs.cs:line 2813
at FluentAssertions.Specs.Equivalency.CollectionEquivalencySpecs.When_an_exception_is_thrown_during_data_access_the_stack_trace_contains_the_original_site() in C:\dev\fluentassertions\Tests\FluentAssertions.Specs\Equivalency\CollectionEquivalencySpecs.cs:line 2817
@dennisdoomen Should this be targeted against the release-6.0 branch?
Yes, I think it's totally fine to get it in 6.0 |
|
Do I have to do something? |
|
Yes, to rebase it on the |
…e is returned from the unwrapping of the TargetInvocationException in GenericEnumerableEquivalencyStep.
…nner exception of the TargetInvocationException, so that the error message contains the correct stack trace.
a2819c4 to
3144bb3
Compare
|
Done. |
|
Oh crap. We also forgot about the release notes. Would you mind adding a line to https://github.com/fluentassertions/fluentassertions/blob/release-6.0/docs/_pages/releases.md? |
|
Done. |
|
Thanks for the contribution! |
This fixes #1613.
When an instance to compare throws an exception during the invocation of the HandleMethod in the Handle method of GenericEnumerableEquivalencyStep, the TargetInvocationException is unwrapped (to give the innermost exception) and rethrown. This previously lead to a wrong stack trace that would indicate, that something is wrong in GenericEnumerableEquivalencyStep.
The first commit provides a test that shows this.
The second commit fixes it by using ExceptionDispatchInfo to capture the stack trace. Since the class ExceptionExtensions is internal, the signature change of the Unwrap method is not changing the public API.
If you do not like the change of the method signature, there is a hack to keep it.
I read that I should add this fix to the release notes. In this branch or another branch?