Wednesday, 15 July 2015

Android espresso onData error



1. The onData we can get is this:


onData(allOf(is(instanceOf(Map.class)), hasEntry(equalTo("STR"), is("item: 50")))
  .perform(click());
from https://code.google.com/p/android-test-kit/wiki/EspressoSamples

2. However, you will never use Map for your data. You will use ProductVO.class or XXXVO.class.

3. Then you can't use "hasEntry" you have to use "hasProperty" such as:

onData(allOf(is(instanceOf(DeliveryVO.class)), hasProperty("deliveryReferenceId", is("1235"))))
        .perform(click());



4. However, you will get this error:

java.lang.NoClassDefFoundError: Failed resolution of: Ljava/beans/Introspector;
at org.hamcrest.beans.PropertyUtil.propertyDescriptorsFor(PropertyUtil.java:47)
at org.hamcrest.beans.PropertyUtil.getPropertyDescriptor(PropertyUtil.java:28)
at org.hamcrest.beans.HasPropertyWithValue.propertyOn(HasPropertyWithValue.java:94)
at org.hamcrest.beans.HasPropertyWithValue.matchesSafely(HasPropertyWithValue.java:81)
at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.java:55)
at org.hamcrest.core.AllOf.matches(AllOf.java:27)
at org.hamcrest.DiagnosingMatcher.matches(DiagnosingMatcher.java:12)
at android.support.test.espresso.action.AdapterDataLoaderAction.perform(AdapterDataLoaderAction.java:83)
at android.support.test.espresso.ViewInteraction$1.run(ViewInteraction.java:144)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)




5. "java.beans.Introspector" is a core java class. As we know android uses java but it doesn't use the full version of java.

6. the reason we use "java.beans.Introspector" is, we are using Espresso for testing and it uses "Hamcrest" which use javaBeans.



7. Solution One:
     Get Hamcrest's source code and remove all javabeans and use openJavaBeans.  ericharlow already did this change, you can use the source code directly:
   
      https://github.com/ericharlow/JavaHamcrest/tree/with-openBeans

    However, you figure out how to exclude hamcrest-library.jar in gradle (we cause we don't directly use hamcrest in gradle, we use espresso and espresso bring it in.) we also need make sure you use the right version of hamcrest to match your espresso.
 
    Even you can solve all of these issues, we need compile it your self and put it into gradle (if you want put it into "libs", that is much easier)

   So, this could be a solution be not good one!!! let's see the solution two below.

8. Solution Two:


   Possible solution: Put java bean jar file into your project. But there is no such jar file, it is in the rt.jar file. If you put rt.jar in you will get error, because it is too much, it is the whole JRE.


   So we will copy the source files we need and put them into our project. you can get all source code of JRE from https://java.net/projects/openjdk6/downloads unzip it and you can get the java file from:


create the same package and copy it over. Because it depends on other files, so you need keep copying. you will endup with:


You will have to delete some code e.g. awt.image which is useless for us. (have to say this is a rubbish architecture design from sun, java bean is a highly abstract things can be used by all java package, awt.* stuff should just inside of awt package.  Due to awt is a part of core java, it is not a big issue. But if we observe it now, in terms of extract java bean, it is rubbish.)

You don't have to manually copy them I already did that and you can download the code from :
    https://github.com/wangpingsx/javabean4androidespresso

After copy, if you compile your code now, you will have this error:

    trouble processing "java/beans/BeanDescriptor.class":
    Ill-advised or mistaken usage of a core class (java.* or javax.*)



Because you attempt to include a core class (java.* or javax.*) in something other than a core library

And it is also ugly to put this code which is for testing into your project even not in "main". So I suggest:







Then download my code from https://github.com/wangpingsx/javabean4androidespresso and put it here or you can override the whole folder of "jdklib" by my folder.


Very importantly, you should put this input your gradle file: (inset of android{})

dexOptions {
    preDexLibraries = false    javaMaxHeapSize "4g"}

project.tasks.withType(com.android.build.gradle.tasks.Dex) {
    additionalParameters=['--core-library']
}


Then in your module setting page:





Rerun your test, you should get:





https://code.google.com/p/android-test-kit/wiki/EspressoSamples
http://stackoverflow.com/questions/24163341/android-studio-ignore-core-library-flag







No comments:

Post a comment