google-code-export / gwt-test-utils

Automatically exported from code.google.com/p/gwt-test-utils
1 stars 0 forks source link

Patching a method returning JavaScriptObject doesn't work. #156

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1.  Create simplest JavaScriptObject and its patcher.
public class SimpleJS extends JavaScriptObject {
    protected SimpleJS() {
    }

    public final native String getString()/*-{
        return this.string;
    }-*/;
}

@PatchClass(SimpleJS.class)
public class SimpleJSPatcher {

    @PatchMethod
    public final static String getString(){
        return "testString";
    }
}

2.  Create a class which uses the SimpleJS.
public class MainClass {

    public MainClass() {
    }

    public int workingJSNIMethod(){
        return getInt();        
    }

        //Patching getInt() works really fine.
    private native static int getInt()/*-{
        return $wnd.integer;
    }-*/;

        //The moment I patch getSimpleJS(), I get error.
    private native SimpleJS getSimpleJS()/*-{
        return $wnd.simpleDto;
    }-*/;
}

@PatchClass(MainClass.class)
public class MainClassPatcher {

    @PatchMethod
    static int getInt(){
        return 10;
    }

    /**
     * It doesn't matter whether I am returning JS or null.
     */
    @PatchMethod
    static SimpleJS getSimpleJS(){
        SimpleJS js = JavaScriptObject.createObject().cast();
        return js;      
    }   
}
3.
@GwtModule("com.test.MyTestModule")
public class MainClassTest extends GwtTestWithEasyMock{

    MainClass mainClass = new MainClass();

    @Test
    public void testSimplestJSNIMethod(){

                //This works fine until I put getSimpleJS() patcher method.
        Assert.assertEquals(10, mainClass.workingJSNIMethod());
    }

        //It doesn't matter whether my test class is referring the JavaScriptObject, I get the NoClassDefFoundFound error.
}

What version of the product are you using? On what operating system?
gwt-test-utils-0.40-20120801.063143-21.jar

Running the above test results in the following error.

java.lang.NoClassDefFoundError: Lcom/test/client/MainClass;
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
    at java.lang.Class.getDeclaredFields(Class.java:1743)
    at org.junit.runners.model.TestClass.<init>(TestClass.java:42)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:65)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:58)
    at com.googlecode.gwt.test.internal.junit.GwtBlockJUnit4ClassRunner.<init>(GwtBlockJUnit4ClassRunner.java:20)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.googlecode.gwt.test.internal.junit.AbstractGwtRunnerFactory.newInstance(AbstractGwtRunnerFactory.java:55)
    at com.googlecode.gwt.test.internal.junit.AbstractGwtRunnerFactory.create(AbstractGwtRunnerFactory.java:34)
    at com.googlecode.gwt.test.internal.junit.AbstractGwtRunner.<init>(AbstractGwtRunner.java:31)
    at com.googlecode.gwt.test.GwtRunner.<init>(GwtRunner.java:19)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
    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)
Caused by: java.lang.ClassNotFoundException: caught an exception while 
obtaining a class file for com.test.client.MainClass
    at com.googlecode.gwt.test.internal.GwtClassLoader.findClassBytes(GwtClassLoader.java:210)
    at com.googlecode.gwt.test.internal.GwtClassLoader$GwtClassLoaderWithRewriter.findClassBytes(GwtClassLoader.java:86)
    at com.googlecode.gwt.test.internal.GwtClassLoader.findClass(GwtClassLoader.java:157)
    at javassist.Loader.loadClass(Loader.java:311)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    ... 33 more
Caused by: com.googlecode.gwt.test.exceptions.GwtTestPatchException: Error 
while patching class 'com.test.client.MainClass'
    at com.googlecode.gwt.test.internal.GwtTranslator.applyPatcher(GwtTranslator.java:67)
    at com.googlecode.gwt.test.internal.GwtTranslator.patchClass(GwtTranslator.java:79)
    at com.googlecode.gwt.test.internal.GwtTranslator.onLoad(GwtTranslator.java:32)
    at com.googlecode.gwt.test.internal.GwtClassLoader.findClassBytes(GwtClassLoader.java:185)
    ... 37 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: 0
    at com.googlecode.gwt.test.internal.AutomaticPatcher.hasCompatibleSignature(AutomaticPatcher.java:299)
    at com.googlecode.gwt.test.internal.AutomaticPatcher.findPatchMethod(AutomaticPatcher.java:158)
    at com.googlecode.gwt.test.internal.AutomaticPatcher.getNewBody(AutomaticPatcher.java:69)
    at com.googlecode.gwt.test.internal.GwtPatcherUtils.patch(GwtPatcherUtils.java:34)
    at com.googlecode.gwt.test.internal.GwtTranslator.applyPatcher(GwtTranslator.java:62)
    ... 40 more

Original issue reported on code.google.com by shivakum...@gmail.com on 6 Aug 2012 at 7:38

GoogleCodeExporter commented 9 years ago

Original comment by gael.laz...@gmail.com on 7 Aug 2012 at 5:51

GoogleCodeExporter commented 9 years ago
The patcher API is expecting the "this" object as the first parameter when you 
use @PatchMethod for non static method. This is explained here : 
http://code.google.com/p/gwt-test-utils/wiki/HowToWriteCustomPatchers#Writing_a_
custom_patcher

Your @PatchMethod getInt() is right since the MainClass.getInt() is static. The 
@PatchMethod getSimpleJS() is not right since the MainClass.getSimpleJS() is 
not static.  Your patch method should be like this : 

   @PatchMethod
   static SimpleJS getSimpleJS(MainClass mainClass) {
      SimpleJS js = JavaScriptObject.createObject().cast();
      return js;
   }

I will improve the thrown Exception to have something more explicit than the 
ArrayOutOfBoundException you get !

Original comment by gael.laz...@gmail.com on 7 Aug 2012 at 9:52