2015-05-14 9 views
7

To jest mój kodu testu:„Animatorzy mogą być prowadzone jedynie na wątkach Looper” podczas intrumentation testowania na urządzeniach

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

} 

Przyciski mam klikający używając espresso są oparte na materiale tematu i pewnie jakieś animacje pod spodem. Rezultat jest taki, że gdy próbuję uruchomić jakieś testy aplikacji intrumentation, awarie aplikacji są generowane za każdym razem, gdy wykonuję kliknięcie. Próbowałem wyłączyć animację w opcjach programistów systemu, ale to nie pomogło.

android.util.AndroidRuntimeException: Animatorzy może pracować tylko na chwytacza gwintu na android.animation.ValueAnimator.start (ValueAnimator.java:1002) w android.animation.ValueAnimator.start (ValueAnimator.java : 1050) pod android.animation.ObjectAnimator.start (ObjectAnimator.java:829) pod android.animation.AnimatorSet.start (AnimatorSet.java:585) pod android.animation.StateListAnimator.start (StateListAnimator.java:187) pod android.animation.StateListAnimator.setState (StateListAnimator.java:180) na android.view.View.drawableStateChanged (View.java:15988) pod adresem android.widget.TextView.drawableStateChanged (TextView.java:3659) pod adresem android.view.View.refreshDrawableState (View.java:16032) pod adresem android.view.View.setEnabled (Widok. java: 6724) pod adresem android.widget.TextView.setEnabled (TextView.java:1446) pod adresem my.app.ui.fragments.welcome.LoginFragment.unlock (LoginFragment.java:263) pod adresem my.app.ui .fragments.welcome.LoginFragment $ 4.success (LoginFragment.java:224) na my.app.ui.fragments.welcome.LoginFragment $ 4.success (LoginFragment.java:222) na my.app.WelcomeActivityTests.testRate (WelcomeActivityTests.java:84) w java.lang.reflect.Method.invoke (metoda macierzysta) pod java.lang.reflect.Method.invoke (Method.java:372) at org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:45) at org.junit.internal.runners.model .ReflectiveCallable.run (ReflectiveCallable.java:15) w org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:42) w org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod .java 20) w org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java:28) w org.junit.internal.runners.statements.RunAfters.evaluate (RunAfters.java:30) pod i roid.support.test.internal.statement.UiThreadStatement.evaluate (UiThreadStatement.java:55) pod adresem android.support.test.rule.ActivityTestRule $ ActivityStatement.evaluate (ActivityTestRule.java:257) at org.junit.rules .RunRules.evaluate (RunRules.java:18) w org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:263) w org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:68) w org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:47) w org.junit.runners.ParentRunner 3,95 USD (ParentRunner.java:231) pod adresem org.junit.runners.ParentRunner $ 1.schedule (ParentRunner. java: 60) at org.junit.runners.ParentRunner.runChildren (ParentRunner.java:229) pod adresem org.junit.runners.ParentRunner.access 000 000 (ParentRunner.java:50) pod adresem org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java:222) pod adresem org.junit.runners.ParentRunner.run (ParentRunner.java: 300) pod adresem org.junit.runners.Suite.runChild (Suite.java:128) pod adresem org.junit.runners.Suite.runChild (Suite.java:24) pod adresem org.junit.runners.ParentRunner 3 USD .run (ParentRunner.java:231) pod adresem org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:60) pod adresem org.junit.runners.ParentRunner.runChildren (ParentRunner.java:229) pod adresem org. junit.runners.ParentRunner.access 000 000 (ParentRunner.java:50) pod adresem org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java:222) pod adresem org.junit.runners.ParentRunner.run (ParentRunner.java: 300) pod adresem org.junit.runner.JUnitCore.run (JUnitCore.java:157) pod adresem org.junit.runner.JUnitCore.run (JUnitCore.java:136) pod adresem android.support.test.internal .runner.TestExecutor.execute (TestExecutor.java:54) na android.support.test.runner.AndroidJUnitRunner.onStart (AndroidJUnitRunner.java:228) na android.app.Instrumentation $ InstrumentationThread.run (Instrumentation.java : 1853)

jest to linia, która rozbija moje app:

btnFacebook.setEnabled(false); 

Edit: znalazłem właściwego rozwiązania, poszukaj akceptowanej odpowiedzi.

Odpowiedz

9

Ok, znalazłem właściwe rozwiązanie! Podczas pracy z bibliotekami i apis, które używają Handlers, musisz opisać swoje przypadki testowe za pomocą @UiThreadTest. Ponadto każdy wywoływany zwrotny asynchronouo powinien być wywoływany przy użyciu metody instrumentation runOnMainSync (Runnable r) . Przykład:

@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

Spróbuj zadzwonić na linię w symulowanym wątku:

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

Dzięki za odpowiedź! To sprawia, że ​​działa, ale nie jest rozwiązaniem. Aplikacja testująca nie powinna mieć żadnego wpływu na kod aplikacji. Będę musiał zawijać każde wywołanie setEnabled i podobnych funkcji wyzwalających animacje w Handlerach, co jest bardzo trudnym obejściem płyty kotła. – pawelo

+0

ale twój kod działa, naprawdę? Jeśli tak, to nie powinno to wpłynąć na twój kod! musisz jakoś zastosować obejście w testach! –

+1

Co mam na myśli to, że moja aplikacja działa dobrze bez obsługi. Przyczyną awarii jest uruchomienie testów oprzyrządowania. Sposób, w jaki runner testu AndroidJUnit4 radzi sobie z moimi wątkami, jest problemem. Myślę, że Retrofit używa Handler'a do przekazania samego Callback, ale jakoś nie działa w środowisku testowym. – pawelo

Powiązane problemy