diff --git a/mock/mock.go b/mock/mock.go index 853da6cce..19a334b6e 100644 --- a/mock/mock.go +++ b/mock/mock.go @@ -812,7 +812,16 @@ func (args Arguments) Diff(objects []interface{}) (string, int) { } if matcher, ok := expected.(argumentMatcher); ok { - if matcher.Matches(actual) { + var matches bool + func() { + defer func() { + if r := recover(); r != nil { + actualFmt = fmt.Sprintf("panic in argument matcher: %v", r) + } + }() + matches = matcher.Matches(actual) + }() + if matches { output = fmt.Sprintf("%s\t%d: PASS: %s matched by %s\n", output, i, actualFmt, matcher) } else { differences++ diff --git a/mock/mock_test.go b/mock/mock_test.go index 91828f813..dd1ebc044 100644 --- a/mock/mock_test.go +++ b/mock/mock_test.go @@ -233,6 +233,32 @@ func Test_Mock_On_WithIntArgMatcher(t *testing.T) { }) } +func Test_Mock_On_WithArgMatcherThatPanics(t *testing.T) { + var mockedService TestExampleImplementation + + mockedService.On("TheExampleMethod2", MatchedBy(func(_ interface{}) bool { + panic("try to lock mockedService") + })).Return() + + defer func() { + assertedExpectations := make(chan struct{}) + go func() { + tt := new(testing.T) + mockedService.AssertExpectations(tt) + close(assertedExpectations) + }() + select { + case <-assertedExpectations: + case <-time.After(time.Second): + t.Fatal("AssertExpectations() deadlocked, did the panic leave mockedService locked?") + } + }() + + assert.Panics(t, func() { + mockedService.TheExampleMethod2(false) + }) +} + func TestMock_WithTest(t *testing.T) { var ( mockedService TestExampleImplementation