"Animators can only run in Looper threads" during device intrusion testing

This is my test code:

@RunWith(AndroidJUnit4.class) @SmallTest public class WelcomeActivityTests extends BaseTest { ApplicationController applicationController; @Rule public ActivityTestRule<WelcomeActivity> activityTestRule = new ActivityTestRule<>(WelcomeActivity.class); ArgumentCaptor<Callback> argumentCaptor; @Before @Override public void setUp() { applicationController = (ApplicationController) InstrumentationRegistry.getTargetContext().getApplicationContext(); applicationController.setMockMode(true); argumentCaptor = ArgumentCaptor.forClass(Callback.class); super.setUp(); } @Test public void testLogin() throws InterruptedException { onView(withId(R.id.btnLogInW)).perform(click()); onView(withId(R.id.email)).perform(typeText(" good.email@example.com ")); onView(withId(R.id.passL)).perform(typeText("strong.password")); onView(withId(R.id.btnLogInL)).perform(click()); User user = new User(); user.first_name = "Fake name"; user.last_name = "Fake name"; user.id = 1; user.email = " fake.email@gmail.com "; AuthResponse authResponse = new AuthResponse(); authResponse.api_key = "fake_api_key"; authResponse.status = "ok"; authResponse.user = user; Mockito.verify(api).login(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), argumentCaptor.capture()); argumentCaptor.getValue().success(authResponse, null); assert true; } @After public void release() { applicationController.setMockMode(false); } } 

The buttons that I press using espresso are based on a material theme, and they probably have some animations below. The result is that when I try to run some testing tests, every time I click, it crashes. I tried to turn off the animation in the settings of system developers, but this did not help.

android.util.AndroidRuntimeException: animators can only run loop Threads on android.animation.ValueAnimator.start (ValueAnimator.java:1002) in android.animation.ValueAnimator.start (ValueAnimator.java:1050) at android.animation.ObjectAnimim (ObjectAnimator.java:829) at android.animation.AnimatorSet.start (AnimatorSet.java=855) in android.animation.StateListAnimator.start (StateListAnimator.java:187) in android.animation.StateListAnimator.setState (StateListnAnaator 180) in android.view.View.drawableStateChanged (View.java:15988) in android.widget.TextView.drawableStateChanged (TextView.javahaps659) in android.view.View.refreshDrawableState (View.java:16032) at android. view.View.setEnabled (View.java:6724) at android.widget.TextView.setEnabled (TextView.java:1446) in my.app.ui.fragments.welcome.LoginFragment.unlock (LoginFragment.java:263) in my .app.ui.fragments.welcome.LoginFragment $ 4.success (LoginFragment.java:224) in my.app.ui.frag ments.welcome.LoginFragment $ 4.success (LoginFragment.java:222) in my.app.WelcomeActivityTests.testRate (WelcomeActivityTests.java:84) in java.lang.reflect.Method.invoke (native method) in java.lang.reflect .Method.invoke (Method.javahaps72) in org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:45) in org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java: 15) in org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:42) in org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java:20) in org.junit.internal.runners .statements.RunBefores.evaluate (RunBefores.java:28) in org.junit.internal.runners.statements.RunAfters.evaluate (RunAfters.java:30) in android.support.test.internal.statement.UiThreadStatement.evaluate (UiThreadStatement .java: 55) at android.support.test.rule.ActivityTestRule $ ActivityStatement.evaluate (ActivityTestRule.java:257) at org.junit.rules.RunRules.evaluate (R unRules.java:18) in org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:263) in org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:68) in org.junrunnerunnerunnerunnerunner (BlockJUnit4ClassRunner.java:47) at org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:231) at org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:60) at org.junit.runners. ParentRunner.runChildren (ParentRunner.java:229) in org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:50) in org.junit.runners.ParentRunner $ 2.value (ParentRunner.java:222) in org.junit .runners.ParentRunner.run (ParentRunner.javahaps00) in org.junit.runners.Suite.runChild (Suite.java:128) in org.junit.runners.Suite.runChild (Suite.java:24) in org. junit.runners.ParentRunner $ 3.run (ParentRunner.java:231) at org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren (ParentRunner.java:9) at org.junit.runners.ParentRunner.a ccess $ 000 (ParentRunner.java:50) at org.junit.runners.ParentRunner $ 2.value (ParentRunner.java:222) at org.junit.runners.ParentRunner.run (ParentRunner.javahaps00) at org.junit.runner .JUnitCore.run (JUnitCore.java:157) in org.junit.runner.JUnitCore.run (JUnitCore.java:136) in android.support.test.internal.runner.TestExecutor.execute (TestExecutor.java:54) in android.support.test.runner.AndroidJUnitRunner.onStart (AndroidJUnitRunner.java:228) in android.app.Instrumentation $ InstrumentationThread.run (Instrumentation.java:1853)

This is the line that breaks my application:

 btnFacebook.setEnabled(false); 

Edit: I found the right solution looking for the accepted answer.

+7
java android junit junit4 android-testing
source share
2 answers

Ok, I found the right solution! When working with libraries and apis using Handlers , you need to annotate your test cases with @UiThreadTest . In addition, each asynchronouos callback that you execute must be called using the toolkit's runOnMainSync (Runnable r) method. Example:

  @Test @UiThreadTest public void testLoginSuccess() { Instrumentation.ActivityMonitor monitor = InstrumentationRegistry.getInstrumentation().addMonitor(EventsListActivity.class.getName(), null, true); onView(withId(R.id.btnLogInW)).perform(click()); onView(withId(R.id.email)).perform(typeText(" good.email@example.com ")); onView(withId(R.id.passL)).perform(typeText("strong.password")); onView(withId(R.id.btnLogInL)).perform(click()); User user = new User(); user.first_name = "Fake name"; user.last_name = "Fake name"; user.id = 1; user.email = " fake.email@gmail.com "; final AuthResponse authResponse = new AuthResponse(); authResponse.api_key = "fake_api_key"; authResponse.status = "ok"; authResponse.user = user; Mockito.verify(api).login(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), argumentCaptor.capture()); InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { argumentCaptor.getValue().success(authResponse, null); } }); assertThat(1, equalTo(monitor.getHits())); InstrumentationRegistry.getInstrumentation().removeMonitor(monitor); } 
+9
source share

Try calling a string in a simulated stream:

 new Handler().postDelayed(new Runnable() { @Override public void run() { btnFacebook.setEnabled(false); } }, 100); 
+1
source share

All Articles