Skip to content
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

Add String method to Mock to fix #423 #694

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,14 @@ type Mock struct {
mutex sync.Mutex
}

// String provides a %v format string for Mock.
// Note: this is used implicitly by Arguments.Diff if a Mock is passed.
// It exists because go's default %v formatting traverses the struct
// without acquiring the mutex, which is detected by go test -race.
func (m *Mock) String() string {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is very strange to implement the stringer method through a pointer and not through a value. most often this method is implemented by value.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xorcare the Mock holds a mutex, so we can't pass by value or the race detector will detect the copy

return fmt.Sprintf("%[1]T<%[1]p>", m)
}

// TestData holds any data that might be useful for testing. Testify ignores
// this data completely allowing you to do whatever you like with it.
func (m *Mock) TestData() objx.Map {
Expand Down
37 changes: 37 additions & 0 deletions mock/mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1497,3 +1497,40 @@ func unexpectedCallRegex(method, calledArg, expectedArg, diff string) string {
func ConcurrencyTestMethod(m *Mock) {
m.Called()
}

func TestConcurrentArgumentRead(t *testing.T) {
methodUnderTest := func(c caller, u user) {
go u.Use(c)
c.Call()
}

c := &mockCaller{}
defer c.AssertExpectations(t)

u := &mockUser{}
defer u.AssertExpectations(t)

done := make(chan struct{})

c.On("Call").Return().Once()
u.On("Use", c).Return().Once().Run(func(args Arguments) { close(done) })

methodUnderTest(c, u)
<-done // wait until Use is called or assertions will fail
}

type caller interface {
Call()
}

type mockCaller struct{ Mock }

func (m *mockCaller) Call() { m.Called() }

type user interface {
Use(caller)
}

type mockUser struct{ Mock }

func (m *mockUser) Use(c caller) { m.Called(c) }