2015-05-14 14 views
7

Questo è il mio codice di prova:"Animatori possono essere eseguito solo su discussioni Looper" durante on-device strumentazione di test

@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("[email protected]")); 
     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 = "[email protected]"; 

     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); 
    } 

} 

pulsanti sto facendo clic con caffè espresso sono basati sul tema di materiali e probabilmente hanno alcune animazioni sotto. Il risultato è che quando provo a eseguire alcuni test di intromissione, l'app si arresta in modo anomalo ogni volta che eseguo un clic. Ho provato a disattivare l'animazione nelle opzioni degli sviluppatori di sistema, ma non ha aiutato.

android.util.AndroidRuntimeException: Animators possono essere eseguiti solo su del crochet a android.animation.ValueAnimator.start (ValueAnimator.java:1002) a android.animation.ValueAnimator.start (ValueAnimator.java : 1050) a android.animation.ObjectAnimator.start (ObjectAnimator.java:829) a android.animation.AnimatorSet.start (AnimatorSet.java:585) a android.animation.StateListAnimator.start (StateListAnimator.java:187) a android.animation.StateListAnimator.setState (StateListAnimator.java:180) su android.view.View.drawableStateChanged (View.java:15988) a android.widget.TextView.drawableStateChanged (TextView.java:3659) a android.view.View.refreshDrawableState (View.java:16032) a android.view.View.setEnabled (Visualizza. java: 6724) a android.widget.TextView.setEnabled (TextView.java:1446) a my.app.ui.fragments.welcome.LoginFragment.unlock (LoginFragment.java:263) a my.app.ui .fragments.welcome.LoginFragment $ 4.success (LoginFragment.java:224) a my.app.ui.fragments.welcome.LoginFragment $ 4.success (LoginFragment.java:222) a my.app.WelcomeActivityTests.testRate (WelcomeActivityTests.java:84) all'indirizzo java.lang.reflect.Method.invoke (metodo nativo) allo java.lang.reflect.Method.invoke (Method.java:372) a org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:45) a org.junit.internal.runners.model .ReflectiveCallable.run (ReflectiveCallable.java:15) a org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:42) a org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod .java: 20) a org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java:28) a org.junit.internal.runners.statements.RunAfters.evaluate (RunAfters.java:30) allo e roid.support.test.internal.statement.UnityThreadStatement.evaluate (UiThreadStatement.java:55) a android.support.test.rule.ActivityTestRule $ ActivityStatement.evaluate (ActivityTestRule.java:257) presso org.junit.rules .RunRules.evaluate (RunRules.java:18) a org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:263) a org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:68) a org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:47) presso org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:231) al org.junit.runners.ParentRunner $ 1.schedule (ParentRunner. java: 60) a org.junit.runners.ParentRunner.runChildren (ParentRunner.java:229) a org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:50) a org.junit.runners.ParentRunner $ 2.valore (ParentRunner.java:222) a org.junit.runners.ParentRunner.run (ParentRunner.java: 300) a org.junit.runners.Suite.runChild (Suite.java:128) a org.junit.runners.Suite.runChild (Suite.java:24) a org.junit.runners.ParentRunner $ 3 .run (ParentRunner.java:231) a org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:60) a org.junit.runners.ParentRunner.runChildren (ParentRunner.java:229) a org. junit.runners.ParentRunner.access $ 000 (ParentRunner.java:50) a org.junit.runners.ParentRunner $ 2.valore (ParentRunner.java:222) a org.junit.runners.ParentRunner.run (ParentRunner.java: 300) a org.junit.runner.JUnitCore.run (JUnitCore.java:157) a org.junit.runner.JUnitCore.run (JUnitCore.java:136) a android.support.test.internal .runner.TestExecutor.execute (TestExecutor.java:54) a android.support.test.runner.AndroidJUnitRunner.onStart (AndroidJUnitRunner.java:228) a android.app.Instrumentation $ InstrumentationThread.run (Instrumentation.java : 1853)

Questa è la linea, che si blocca la mia app:

btnFacebook.setEnabled(false); 

Edit: ho trovato soluzione adeguata, cercare risposta accettata.

risposta

9

Ok, ho trovato una soluzione adeguata! Quando si tratta di librerie e apis che utilizzano gli handler , è necessario annotare i casi di test con @UiThreadTest. Inoltre, ogni callback asincrono che si sta eseguendo deve essere richiamato utilizzando il metodo runOnMainSync (Runnable r) Instrumentation. Esempio:

@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("[email protected]")); 
     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 = "[email protected]"; 

     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); 
    } 
1

tenta di chiamare la linea in un thread simulato:

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

Grazie per la risposta! Lo fa funzionare ma non è la soluzione. L'app di test non dovrebbe avere alcun impatto sul codice dell'app. Avrei bisogno di racchiudere tutte le invocazioni di setEnabled e funzioni simili che attivano le animazioni in Handler, che è una soluzione molto pesante per la piastra di riscaldamento. – pawelo

+0

ma il tuo codice funziona davvero? Se è così, non ci sarà alcun impatto sul tuo codice! devi applicare la soluzione alternativa nei test in qualche modo! –

+1

Quello che intendevo è che la mia app funziona perfettamente senza Handler. Ciò che lo rende in crash è l'esecuzione di test strumentali. Il modo in cui il runner di prova di AndroidJUnit4 gestisce i miei thread è il problema. Penso che Retrofit usi Handler per passare Callback stesso, ma in qualche modo non funziona nell'ambiente di testing. – pawelo

Problemi correlati