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

Lambda in assertArg called twice #5

Open
CalamarBicefalo opened this issue Jan 6, 2016 · 3 comments
Open

Lambda in assertArg called twice #5

CalamarBicefalo opened this issue Jan 6, 2016 · 3 comments

Comments

@CalamarBicefalo
Copy link

We have found an interesting issue, that seems to be caused by assertArg. For the following test

    verify(mockedService).functionThatExpectsAnInputStream(assertArg((InputStream is) -> {
            try {
                // Oh my god this thing gets invoked twice !! 
                assertThat(IOUtils.toByteArray(is),is("a,b,c".getBytes()));
            } catch (IOException e) {
                fail();
            }
        }));

The lambda block gets invoked twice, being the IS in the second execution empty.

However if the same logic is done using a regular ArgumentCaptor, it works as expected (a single execution is done):

        ArgumentCaptor<InputStream> is = ArgumentCaptor.forClass(InputStream.class);
        verify(mockedService).functionThatExpectsAnInputStream(is.capture());
        assertThat(is.getValue(),notNullValue());
        assertThat(IOUtils.toByteArray(is.getValue()),is("a,b,c".getBytes()));

We could provide further context if needed.

Thank you very much.

@szpak
Copy link
Owner

szpak commented Mar 27, 2016

Thanks for your report and sorry for delay.

It looks like that DispatcherDefaultingToRealMethod.interceptSuperCallable() is called twice which results in double execution of passed lambda and I don't know how much I can do about that. In case of "classic" verify construction this method (from Byte Buddy creation package) is also called twice, but it is later cut off at some level and in the end captor.capture() is not called twice.

@raphw is it normal/required to have DispatcherDefaultingToRealMethod.interceptSuperCallable() called twice? Maybe you have any good suggestion what could be done with this issue?

@szpak
Copy link
Owner

szpak commented Mar 27, 2016

@raphw
Copy link

raphw commented Apr 2, 2016

Hi, I think this is an implementation detail of Mockito and has nothing to do with Byte Buddy. The problem occures in the Times class:

public void verify(VerificationData data) {
  if(this.wantedCount > 0) {
    MissingInvocationChecker numberOfInvocations = new MissingInvocationChecker();
    numberOfInvocations.check(data.getAllInvocations(), data.getWanted()); // 1
  }
  NumberOfInvocationsChecker numberOfInvocations1 = new NumberOfInvocationsChecker();
  numberOfInvocations1.check(data.getAllInvocations(), data.getWanted(), this.wantedCount); // 2
}

The matcher is triggered once by (1) and once by (2). I assume that the original implementation did not consider that the matchers would trigger mutation.

The easiest solution would be to fix this in Mockito, to be honest. A quicker fix would be to wrap the matchers to cache the result of the previous invocation.

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

3 participants