-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Open
Labels
Description
This is a fairly contrived example, I admit. But this was a real head-scratcher in the wild.
The following code will never complete.
package main
import (
"fmt"
"github.com/stretchr/testify/mock"
)
type K struct {
mock.Mock
}
func (f *K) String() string {
return f.Called().Get(0).(string)
}
func (f *K) Foo(b B) string {
return f.Called(b).Get(0).(string)
}
type B struct {
Kay *K
}
func main() {
k := &K{}
b := B{
Kay: k,
}
k.On("String").Return("string-return")
k.On("Foo", b).Return("foo-return")
fmt.Printf(k.Foo(b))
}
This fails because Mock.Called
calls Mock.MethodCalled
, which locks the Mutex, and eventually calls Arguments.Diff
. When Arguments.Diff
calls fmt.Sprintf
, fmt.Sprintf
sees the Kay
field of B
. Since K
implements fmt.Stringer
, fmt.Sprintf
calls K.String
. Since this is a mocked function, K.String
jumps into Mock.Called
, which calls Mock.MethodCalled
which waits for the still-locked mutex to unlock, which never happens, because the lock is further up the call chain.
I don't know if this should be considered a bug or not, but it certainly was unexpected, and took a lot of digging to figure out.
devdinu and rodnymolina