Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Add argument captors #262

Open
Open
@tylersammann

Description

@tylersammann

Description

I think it would be nice to build an ArgumentCaptor interface and argumentCaptor struct that extends Matcher through composition, but store the value of the arguments before the "match" step. Those argument values could then be retrieved for later assertions (very close to how Mockito's ArgumentCaptors work in Java) https://static.javadoc.io/org.mockito/mockito-core/2.6.9/org/mockito/ArgumentCaptor.html

Use Case

I recently ran into a situation where I wanted to write a test that asserted something about the contents of an argument (a slice of struct pointers) passed to a mocked method. Using matchers as they currently exist (i.e. eqMatcher), I couldn't find a good way to do that without already knowing the memory addresses of the pointers in the slice.

Activity

changed the title [-]Add argument captors to gomock[/-] [+]Add argument captors[/+] on Feb 7, 2019
poy

poy commented on Feb 12, 2019

@poy
Collaborator

Have you looked at the gomock.Do() (docs)? It seems like this would get you pretty close.

tylersammann

tylersammann commented on Feb 12, 2019

@tylersammann
Author

Thanks for the reply @poy! Yes, I started writing my tests with gomock.Do() and it was working ok. However, the methods I was mocking had long complicated signatures, so the anonymous funcs I needed to pass to Do() were very long. The ArgumentCaptors get the same end result with a lot less code in those situations.

tylersammann

tylersammann commented on Feb 12, 2019

@tylersammann
Author

I also tried writing a decorator function for passing into Do() that looked something like this.

func ArgumentCaptor(capturedArgs []interface{}) func(args ...interface{}) {
	return func(args ...interface{}) {
		if len(capturedArgs) != len(args) {
			panic(fmt.Sprintf("The capturedArgs array length %d did not match the actual argument count %d",
				len(capturedArgs), len(args)))
		}
		for i, arg := range args {
			capturedArgs[i] = arg
		}
	}
}

It involves writing less code, but its downside was the need to grab the arguments based on their order in the signature with an index.

poy

poy commented on Feb 24, 2019

@poy
Collaborator

@tylersammann

Sorry for the slow response. @balshetzer and I are discussing how we would like to approach adding matchers. I'll let you know what decide!

tylersammann

tylersammann commented on Jun 5, 2019

@tylersammann
Author

@poy @balshetzer Any news here?

shivasuri

shivasuri commented on Aug 28, 2019

@shivasuri

+1

Infiniverse

Infiniverse commented on Dec 1, 2019

@Infiniverse

+1

hgl

hgl commented on Jan 5, 2020

@hgl

@poy @balshetzer

I'm struggling to test the following scenario with Do():

Say my function foo() calls two mocked method .F1() and .F2(), I want to test the argument passed to .F1() is the same as the one passed to .F2()

var arg string
mockStruct.EXPECT()
	.F1(gomock.Any())
	.Do(func(_arg string) { arg = _arg})
mockStruct.EXPECT()
	.F2(gomock.Any(), gomock.Eq(arg))
foo()

This obviously won't work. Any good way to test this right now or the new matchers can help with that?

self-assigned this
on Jan 8, 2020
tylersammann

tylersammann commented on Feb 11, 2020

@tylersammann
Author

@hgl I think there might be a way to do something similar to this with .Do(), but it would involve storing the arguments used in both F1 and F2 and comparing them afterwards. FWIW, here is how I think I'd do with with my argument captor implementation from this PR #263

f1Captor := gomock.AnyCaptor()
f2Captor := gomock.AnyCaptor()

mockStruct.EXPECT().F1(f1Captor)
mockStruct.EXPECT().F2(f2Captor)
foo()

assert.Equal(t, f1Captor.Value(), f2Captor.Value())
added this to the v1.5.0 milestone on Mar 4, 2020
removed this from the v1.5.0 milestone on Jun 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @tylersammann@minicuts@Infiniverse@codyoss@poy

      Issue actions

        Add argument captors · Issue #262 · golang/mock