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

Mocked UiBinder type is erased #51

Open
cushon opened this issue Feb 13, 2015 · 1 comment
Open

Mocked UiBinder type is erased #51

cushon opened this issue Feb 13, 2015 · 1 comment

Comments

@cushon
Copy link
Contributor

cushon commented Feb 13, 2015

I think is is distinct from #50.

In the following example the type of the UiBinder is erased when it is mocked, causing a ClassCastException.

I think there's type information available at runtime that could be used to fixed this. For example, see mockito's handling of RETURNS_DEEP_STUBS with generic types:

Here's the example:

@RunWith(GwtMockitoTestRunner.class)
public class MyWidgetTest {

  interface Appearance {
    // Mocked type will be erased to `UIBinder`
    UiBinder<? extends Widget, ?> uiBinder();
  }

  static class Widget {
    public Widget() {
      Appearance appearance = GWT.create(Appearance.class);
      // Assignment fails with CCE
      Widget widget = appearance.uiBinder().createAndBindUi(null);
    }
  }

  @Before
  public void setUp() {
    new Widget();
  }

  @Test
  public void simpleTest() {
    System.err.println("Hello world");
  }
}

Full repro:

mkdir -p src/test/java/mockitobug/
curl https://gist.githubusercontent.com/cushon/8c231f89708dadcf0075/raw/d9e50510499132037cac47dbd8ad67854fe8b429/MyWidgetTest.java > src/test/java/mockitobug/MyWidgetTest.java
curl https://gist.githubusercontent.com/cushon/50a9cbe451e7d6607a65/raw/94d77af02627d2b7b1756ff14e7a396514d7aeaa/pom.xml > pom.xml
mvn test
Running mockitobug.MyWidgetTest
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.514 sec <<< FAILURE!
simpleTest(mockitobug.MyWidgetTest)  Time elapsed: 0.216 sec  <<< ERROR!
java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$99e9e895 cannot be cast to mockitobug.MyWidgetTest$Widget
    at mockitobug.MyWidgetTest$Widget.<init>(MyWidgetTest.java:22)
    at mockitobug.MyWidgetTest.setUp(MyWidgetTest.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        ...
@ekuefler
Copy link
Collaborator

Thanks for the detailed report. I agree we should have the type information available somewhere at runtime, but it looks quite tricky to get it. I'll take a look at this when I get a chance (which might be a while), or feel free to give it a try yourself.

To some extent this is an issue with the underlying Mockito implementation. We construct mocks using Mockito's ReturnsMocks setting, so presumably it would display the same behavior if used directly. It would be nice if there were a solution that worked by changing how we used mockito rather than adding additional logic on top of that. One thing to explore would be making ReturnsCustomMocks extend ReturnsDeepStubs rather than ReturnsMocks. I experimented with this briefly and it solved the issue you reported, but seemed to create others.

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