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

Problem verifying bridge methods #304

Closed
fbaro opened this issue Oct 13, 2015 · 4 comments
Closed

Problem verifying bridge methods #304

fbaro opened this issue Oct 13, 2015 · 4 comments
Assignees
Labels

Comments

@fbaro
Copy link

fbaro commented Oct 13, 2015

Hello, I think there might be a bug in mockito when verifying bridge methods.
The bug is present both in version 2.0.31-beta, and in version 1.10.19.

import java.io.Serializable;
import org.junit.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class MockitoBridgeTest {

    @Test
    public void test() {
        Extended ext = mock(Extended.class);
        ext.test("123");
        verify(ext).test("123"); // Passes
        ((Base<String>)ext).test("456");
        verify(ext).test("456"); // Fails
    }

    public interface Base<T extends Serializable> {
        int test(T value);
    }

    public interface Extended extends Base<String> {
        @Override
        int test(String value);
    }

}
@raphw
Copy link
Member

raphw commented Oct 13, 2015

The problem here is the following: Byte Buddy does not intercept bridge methods but assumes that these methods should be dispatched as they are. Therefore, the actual method is still invoked which is then intercepted. As a result, the Method instance that is bound to this interception is the actual method, i.e. test(String) and not test(Serializable) which was identified as the bridge. The behavior of cglib is similar.

Mockito on the other hand picks up the invoked method from the call site which is test(Serializable) fpr the secod example. Therefore, Mockito claims that another method is invoked. Instead, Mockito would need to resolve the method to its actual target in order to validate that this method is a bridge for test(String).

I am going to look into how this can be added to Mockito. This requires resolving parameterized tyes along the hierarchy in order to find out to what method the bridge is actually pointing to.

@fbaro
Copy link
Author

fbaro commented Oct 20, 2015

Since somebody else has this issue, I found a workaround to make the test pass:

        ((Base<String>)ext).test("456");
        verify(ext).test("456"); // Fails
        ((Base<String>)verify(ext)).test("456"); // Passes (workaround)

@raphw raphw self-assigned this Nov 10, 2015
@raphw raphw added the bug label Nov 10, 2015
@raphw
Copy link
Member

raphw commented Dec 31, 2015

@bric3 Would it be a feasible solution if I relied on Byte Buddy APIs to resolve this? I implemented a rather elaborate algorithm that I have tried to port to Mockito. However, its not as easy as I thought since the algorithm and related data structure are quite bound into the Byte Buddy APIs. I would of course add an interface that does not rely on Byte Buddy for querying this information but asking the library to do it would be the most straight-forward solution.

@bric3
Copy link
Contributor

bric3 commented Jan 1, 2016

@raphw That is possible, maybe in the form of a Plugin that ByteBuddy mockmaker implement, maybe we would need a default implementation, i.e. that does nothing.

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

No branches or pull requests

3 participants