google / gwtmockito

Better GWT unit testing
https://google.github.io/gwtmockito
Apache License 2.0
157 stars 50 forks source link

ClassCastException: cannot be cast to com.google.gwt.dom.client.AnchorElement #33

Closed DKnight2014 closed 9 years ago

DKnight2014 commented 10 years ago

I am new to gwtmockito and I really like it. But here is an issue that caught me.

A simplified class is like this // a class needs to be tested public class MyClass { Anchor obj;

public MyClass(String userName) {
        //this will fail with GwtMockito
        obj= new Anchor();
}

}

the class to test it is: //a test class @RunWith(GwtMockitoTestRunner.class) public class MyClass_Test { MyClass app;

@Before
public void setUp() {
    //this will fail with GwtMockito
    app = new MyClass("");
}

@Test
public void test1() {
    Assert.assertTrue(true);
}

}

however, when I run this test code, I get an error like this

java.lang.ClassCastException: com.google.gwt.user.client.Element$$EnhancerByMockitoWithCGLIB$$86942b16 cannot be cast to com.google.gwt.dom.client.AnchorElement at com.google.gwt.dom.client.AnchorElement.as(AnchorElement.java:34) at com.google.gwt.user.client.ui.Anchor.getAnchorElement(Anchor.java:564) at com.google.gwt.user.client.ui.Anchor.(Anchor.java:119) at com.google.gwt.user.client.ui.Anchor.(Anchor.java:104) at com.sample.failed.MyClass.(MyClass.java:13) at com.sample.failed.MyClass_Test.setUp(MyClass_Test.java:22) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at com.google.gwtmockito.GwtMockitoTestRunner.run(GwtMockitoTestRunner.java:284) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

I am using gwtmockito 1.1.3 and gwt v2.5.1 with eclipse Kepler v4.3 (x64). GWT doesn't seem to like "new Anchor()" with gwtmockito. can you help me on this??

PS, it seems to make the code quoted automatically but improperly, not sure how to make it right, sorry about that.

thanks,

Edit: This seems very common with GWT classes. Here is another example: java.lang.ClassCastException: com.google.gwt.user.client.Element$$EnhancerByMockitoWithCGLIB$$44131348 cannot be cast to com.google.gwt.dom.client.SelectElement at com.google.gwt.user.client.ui.ListBox.getSelectElement(ListBox.java:600) at com.google.gwt.user.client.ui.ListBox.insertItem(ListBox.java:346) at com.google.gwt.user.client.ui.ListBox.insertItem(ListBox.java:328) at com.google.gwt.user.client.ui.ListBox.insertItem(ListBox.java:295) at com.google.gwt.user.client.ui.ListBox.addItem(ListBox.java:173)

addItem is called by MyClass, but when testing MyClass, this error occurs. can't GwtMockito handle casting within GWT classes?

Please help.... this makes me desperate.

ekuefler commented 10 years ago

Not your fault - GwtMockito has some inherent difficulties in dealing with some of the casts that GWT does internally, since they work in a dynamic language like Javascript but don't make sense in a statically typed language like Java. I've been having to add workarounds whenever people run into trouble, so thanks a lot for reporting these.

I've fixed the issue with Anchor and ListBox and uploaded a new snapshot version - can you confirm that this fixes things for you? Are there any other ClassCast problems you're seeing?

A way you can deal with this problem in general is to use UiBinder or dependency injection. If you use "new" to create widgets, you'll get real widgets that might have surprising behavior when you try to use them from a unit test. If you create your widgets via UiBinder and @UiField, then GwtMockito will automatically inject them with Mockito mocks that you have full control over. Similarly, you can inject the widgets directly into your class yourself and pass your own mocks in tests. So you might be able to work around some of these problems by restructuring a bit, but please do continue reporting them so I can find and fix them.

DKnight2014 commented 10 years ago

hey, thank you so much. It's working now for both of the classes. Those are what I've found so far and I will report it if something like this happens again.

should I close the issue or you want to handle it yourself? thanks.

DKnight2014 commented 10 years ago

Hi ekuefler, Sorry, I think I found another similar issue. it happens when creating com.google.gwt.user.cellview.client.DataGrid

here is the exception: java.lang.ClassCastException: com.google.gwt.dom.client.DivElement$$EnhancerByMockitoWithCGLIB$$86753fad cannot be cast to com.google.gwt.user.client.Element at com.google.gwt.user.client.ui.HeaderPanel.(HeaderPanel.java:82) at com.google.gwt.user.cellview.client.DataGrid.(DataGrid.java:586) at com.google.gwt.user.cellview.client.DataGrid.(DataGrid.java:570) at com.google.gwt.user.cellview.client.DataGrid.(DataGrid.java:557)

ekuefler commented 10 years ago

Added a potential fix for data grids in 3abecd684fe2109616c9cbf2e9c84c9ac962f129 and uploaded a new snapshot. Can you try it out? This should fix creating new data grids, not sure if there will still be problems using them.

DKnight2014 commented 9 years ago

Thank you so much, that fixed the issue.

krishnasv369 commented 9 years ago

Hi ekuefler.

i am facing same kind of issue with "RadioButton".

java.lang.ClassCastException: com.google.gwt.user.client.Element$$EnhancerByMockitoWithCGLIB$$e41b1350 cannot be cast to com.google.gwt.dom.client.InputElement

is there any work around without modifying GWT kit .

and also i dont want to use uibider. since i have committed my huge code already and now i now i cant change to uibinder.

so let me know is there any way of fixing code. thanks in advance .

ekuefler commented 9 years ago

@krishnasv369, Thanks for pointing that one out. I've inserted a fix that will work around the problem in the next version of GwtMockito, which will be released in a week or two. Until then you can either try using the snapshot version or add the following annotation to the test class that's giving you trouble:

@WithClassesToStub(CheckBox.class)

That should also work around the problem for you.