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

Variadic Issue? not really sure. #112

Open
flyinprogrammer opened this issue Nov 21, 2020 · 3 comments
Open

Variadic Issue? not really sure. #112

flyinprogrammer opened this issue Nov 21, 2020 · 3 comments

Comments

@flyinprogrammer
Copy link

Context: See the context here: #111

Oh hello again!!

upside_down_sloth


So now I've made a new discovery! I've tried mocking out this fancy PostMessage method in the slack client:

https://github.com/slack-go/slack/blob/master/chat.go#L123

So I wrote an interface and simple wrapper method to mock out something we sort of do in the Atlantis app:

type SlackClient interface {
	PostMessage(channelID string, options ...slack.MsgOption) (respChannel string, respTimestamp string, err error)
}

func MakeSomething(client SlackClient, channelID string, text string) error {
	_, _, err := client.PostMessage(channelID, slack.MsgOptionText(text, false))
	return err
}

And then a simple test to ensure that our slack client receives something we expect:

func TestPostMessage(t *testing.T)  {
	pegomock.RegisterMockTestingT(t)
	mock := mocks.NewMockSlackClient()
	channelID := "something"
	text := "secret message"
	awesomeProject.MakeSomething(mock, channelID, text)
	mock.VerifyWasCalledOnce().PostMessage(channelID, slack.MsgOptionText(text, false))
}

And it goes 💥 with:

--- FAIL: TestPostMessage (0.00s)
    testing_t_support.go:41: 
                ${HOME}/go/pkg/mod/github.com/petergtz/[email protected]+incompatible/testing_t_support.go:40 +0x5e
        github.com/petergtz/pegomock.(*GenericMock).Verify(0xc00000e4a0, 0x0, 0x12cae40, 0xc00007ef00, 0x127a246, 0xb, 0xc00000e500, 0x2, 0x2, 0xc000059ed0, ...)
                ${HOME}/go/pkg/mod/github.com/petergtz/[email protected]+incompatible/dsl.go:153 +0x5be
        awesomeProject/mocks.(*VerifierMockSlackClient).PostMessage(0xc000059f48, 0x1279af1, 0x9, 0xc000059f40, 0x1, 0x1, 0x0)
                ${HOME}/go/src/awesomeProject/mocks/mock_slack_client.go:96 +0x267
        awesomeProject_test.TestPostMessage(0xc000001b00)
                ${HOME}/go/src/awesomeProject/slack_test.go:17 +0x1b7
        testing.tRunner(0xc000001b00, 0x128d170)
                /usr/local/go/src/testing/testing.go:1123 +0xef
        created by testing.(*T).Run
                /usr/local/go/src/testing/testing.go:1168 +0x2b3
        
        Mock invocation count for PostMessage("something", (slack.MsgOption)(0x11f3f40)) does not match expectation.
        
                Expected: 1; but got: 0
        
                But other interactions with this mock were:
                PostMessage("something", (slack.MsgOption)(0x11f3f40))
FAIL
exit status 1
FAIL    awesomeProject  0.284s

Which is quite odd because it was invoked with the signature, but somehow it wasn't?

Here's the example project: https://github.com/flyinprogrammer/pegomock_examples/tree/issue/variadic

I've tried debugging this in GoLand, but unfortunately I am 🥔. I'll keep poking this to learn how this project works, but if someone happens to know a workaround, or is up for teaching me how or what went wrong I'd love to learn.

@petergtz
Copy link
Owner

petergtz commented Nov 23, 2020

Hello again @flyinprogrammer,

So just started looking into this and it is weird, because there's an actual unit test for this:

pegomock/dsl_test.go

Lines 730 to 780 in e07328a

Context("2 normal arguments and one variadic", func() {
It("succeeds when verifying all captured arguments (one invocation match)", func() {
display.NormalAndVariadicParam("one", 2, "three", "four")
display.NormalAndVariadicParam("five", 6, "seven", "eight", "nine")
stringArg, intArg, varArgs := display.VerifyWasCalled(AtLeast(1)).NormalAndVariadicParam(AnyString(), AnyInt(), AnyString(), AnyString()).GetAllCapturedArguments()
Expect(stringArg[0]).To(Equal("one"))
Expect(intArg[0]).To(Equal(2))
Expect(varArgs[0][0]).To(Equal("three"))
Expect(varArgs[0][1]).To(Equal("four"))
stringArg, intArg, varArgs = display.VerifyWasCalled(AtLeast(1)).NormalAndVariadicParam(AnyString(), AnyInt(), AnyString(), AnyString(), AnyString()).GetAllCapturedArguments()
Expect(stringArg[0]).To(Equal("five"))
Expect(intArg[0]).To(Equal(6))
Expect(varArgs[0][0]).To(Equal("seven"))
Expect(varArgs[0][1]).To(Equal("eight"))
Expect(varArgs[0][2]).To(Equal("nine"))
})
It("succeeds when verifying all captured arguments (multiple invocation matches)", func() {
display.NormalAndVariadicParam("one", 2, "three", "four")
display.NormalAndVariadicParam("five", 6, "seven", "eight", "nine")
display.NormalAndVariadicParam("ten", 11, "twelf", "thirteen", "fourteen")
stringArg, intArg, varArgs := display.VerifyWasCalled(AtLeast(1)).NormalAndVariadicParam(AnyString(), AnyInt(), AnyString(), AnyString()).GetAllCapturedArguments()
Expect(stringArg[0]).To(Equal("one"))
Expect(intArg[0]).To(Equal(2))
Expect(varArgs[0][0]).To(Equal("three"))
Expect(varArgs[0][1]).To(Equal("four"))
stringArg, intArg, varArgs = display.VerifyWasCalled(AtLeast(1)).NormalAndVariadicParam(AnyString(), AnyInt(), AnyString(), AnyString(), AnyString()).GetAllCapturedArguments()
Expect(stringArg[0]).To(Equal("five"))
Expect(intArg[0]).To(Equal(6))
Expect(varArgs[0][0]).To(Equal("seven"))
Expect(varArgs[0][1]).To(Equal("eight"))
Expect(varArgs[0][2]).To(Equal("nine"))
Expect(stringArg[1]).To(Equal("ten"))
Expect(intArg[1]).To(Equal(11))
Expect(varArgs[1][0]).To(Equal("twelf"))
Expect(varArgs[1][1]).To(Equal("thirteen"))
Expect(varArgs[1][2]).To(Equal("fourteen"))
})
It("does not panic when variadic arg has 0 params", func() {
display.VerifyWasCalled(Never()).NormalAndVariadicParam(AnyString(), AnyInt()).GetAllCapturedArguments()
display.NormalAndVariadicParam("one", 2)
display.VerifyWasCalledOnce().NormalAndVariadicParam(AnyString(), AnyInt()).GetAllCapturedArguments()
})
})

So taking a deeper look at it right now.

@petergtz
Copy link
Owner

Actually, now that I look at it, these tests only use the argument capture mechanism. Need to check why this is the case (sorry, written this 4 years ago 😬 )

@petergtz
Copy link
Owner

Ah. The crux is here:

pegomock/dsl.go

Lines 371 to 374 in 6d417a0

func (matchers Matchers) Matches(params []Param) bool {
if len(matchers) != len(params) { // Technically, this is not an error. Variadic arguments can cause this
return false
}

This logic is wrong and must be fixed. It might not be as simple as removing this check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants