The view I'm testing has animation and it seems to go quite wrong when I test with Robolectric. The animation is a simple slide away using Nineoldandroids for compatibility. All works fine outside of Robolectric, however my unit test is crashing with null pointer:
10:34:35.419 [DEBUG] [TestEventLogger] java.lang.NullPointerException
10:34:35.419 [DEBUG] [TestEventLogger] at com.nineoldandroids.view.animation.AnimatorProxy.applyTransformation(AnimatorProxy.java:316)
10:34:35.419 [DEBUG] [TestEventLogger] at android.view.animation.Animation.getTransformation(Animation.java:870)
10:34:35.420 [DEBUG] [TestEventLogger] at org.robolectric.shadows.ShadowView$2.run(ShadowView.java:492)
10:34:35.420 [DEBUG] [TestEventLogger] at org.robolectric.util.Scheduler.runOrQueueRunnable(Scheduler.java:218)
10:34:35.420 [DEBUG] [TestEventLogger] at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:73)
10:34:35.421 [DEBUG] [TestEventLogger] at org.robolectric.shadows.ShadowChoreographer.postCallbackDelayed(ShadowChoreographer.java:44)
10:34:35.421 [DEBUG] [TestEventLogger] at android.view.Choreographer.postCallbackDelayed(Choreographer.java)
10:34:35.427 [DEBUG] [TestEventLogger] at org.robolectric.shadows.ShadowView.setAnimation(ShadowView.java:487)
10:34:35.429 [DEBUG] [TestEventLogger] at android.view.View.setAnimation(View.java)
10:34:35.431 [DEBUG] [TestEventLogger] at com.nineoldandroids.view.animation.AnimatorProxy.<init>(AnimatorProxy.java:66)
10:34:35.432 [DEBUG] [TestEventLogger] at com.nineoldandroids.view.animation.AnimatorProxy.wrap(AnimatorProxy.java:38)
10:34:35.432 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.PreHoneycombCompat$14.get(PreHoneycombCompat.java:161)
10:34:35.432 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.PreHoneycombCompat$14.get(PreHoneycombCompat.java:153)
10:34:35.432 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.PropertyValuesHolder.setupSetterAndGetter(PropertyValuesHolder.java:510)
10:34:35.433 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.ObjectAnimator.initAnimation(ObjectAnimator.java:410)
10:34:35.433 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.ValueAnimator.setCurrentPlayTime(ValueAnimator.java:538)
10:34:35.433 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.ValueAnimator.start(ValueAnimator.java:928)
10:34:35.433 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.ValueAnimator.start(ValueAnimator.java:951)
10:34:35.433 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.ObjectAnimator.start(ObjectAnimator.java:385)
10:34:35.433 [DEBUG] [TestEventLogger] at com.nineoldandroids.animation.AnimatorSet.start(AnimatorSet.java:502)
If I add a check in my code to only use nineoldandroids for API <11 and by default use android native animation the test passes just fine. From the nineoldandroids source I can see that it's null pointering on this line:
View view = mView.get();
where mView is mView = new WeakReference<View>(view);
Any suggestions how to work around this ideally from the test case and not my app code?
What seems to be happening is that the Nineoldandroid animation that animates the list element gets executed by the UI/Main looper before the AnimationProxy
has fully initialised. This could be due to better simulation of the Android threading architecture in Robolectric 3.
I resolved this by calling :
ShadowLooper.pauseMainLooper();
Placing this call before any method that could initiate an animation within Nineoldandroids.
Update:
This was causing more hassle for me and the workaround above was annoying to roll out to every bit of code that did an animation so I forked and fixed it, very small change :
https://github.com/apinder/NineOldAndroids/commit/6d399685dc5b3932e3b806d4d7d2f27123e1ca36