Skip to content

Commit

Permalink
compare unwrapped errors using DeepEqual (#617)
Browse files Browse the repository at this point in the history
  • Loading branch information
tareksha committed Jan 14, 2023
1 parent 9351dda commit aaeaa5d
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 2 deletions.
4 changes: 3 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,9 @@ succeeds if `ACTUAL` is a non-nil `error` that matches `EXPECTED`. `EXPECTED` mu

- A string, in which case `ACTUAL.Error()` will be compared against `EXPECTED`.
- A matcher, in which case `ACTUAL.Error()` is tested against the matcher.
- An error, in which case `ACTUAL` and `EXPECTED` are compared via `reflect.DeepEqual()`. If they are not deeply equal, they are tested by `errors.Is(ACTUAL, EXPECTED)`. (The latter allows to test whether `ACTUAL` wraps an `EXPECTED` error.)
- An error, in which case anyo of the following is satisfied:
- `errors.Is(ACTUAL, EXPECTED)` returns `true`
- `ACTUAL` or any of the errors it wraps (directly or indirectly) equals `EXPECTED` in terms of `reflect.DeepEqual()`.

Any other type for `EXPECTED` is an error.

Expand Down
12 changes: 11 additions & 1 deletion matchers/match_error_matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,17 @@ func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err e
expected := matcher.Expected

if isError(expected) {
return reflect.DeepEqual(actualErr, expected) || errors.Is(actualErr, expected.(error)), nil
// first try the built-in errors.Is
if errors.Is(actualErr, expected.(error)) {
return true, nil
}
// if not, try DeepEqual along the error chain
for unwrapped := actualErr; unwrapped != nil; unwrapped = errors.Unwrap(unwrapped) {
if reflect.DeepEqual(unwrapped, expected) {
return true, nil
}
}
return false, nil
}

if isString(expected) {
Expand Down
15 changes: 15 additions & 0 deletions matchers/match_error_matcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ func (c CustomError) Error() string {
return "an error"
}

type ComplexError struct {
Key string
}

func (t *ComplexError) Error() string {
return fmt.Sprintf("err: %s", t.Key)
}

var _ = Describe("MatchErrorMatcher", func() {
Context("When asserting against an error", func() {
When("passed an error", func() {
Expand All @@ -37,6 +45,12 @@ var _ = Describe("MatchErrorMatcher", func() {

Expect(outerErr).Should(MatchError(innerErr))
})

It("uses deep equality with unwrapped errors", func() {
innerErr := &ComplexError{Key: "abc"}
outerErr := fmt.Errorf("outer error wrapping: %w", &ComplexError{Key: "abc"})
Expect(outerErr).To(MatchError(innerErr))
})
})

When("actual an expected are both pointers to an error", func() {
Expand Down Expand Up @@ -130,6 +144,7 @@ var _ = Describe("MatchErrorMatcher", func() {
})
Expect(failuresMessages[0]).To(ContainSubstring("{s: \"foo\"}\nnot to match error\n <string>: foo"))
})

})

type mockErr string
Expand Down

0 comments on commit aaeaa5d

Please sign in to comment.