2017-02-22 96 views
1

我想測試我的SplashActivity正確啓動HomeActivity如果用戶登錄。意式濃縮咖啡測試失敗:希望匹配1個意圖。其實匹配0意圖

我已經看過StackOverflow上相關的問題,這似乎是一個常見的問題,但我似乎無法得到任何東西工作。

我已經看過測試在我的設備上執行,並通過視覺驗證SplashActivity確實啓動了HomeActivity。

HomeActivity期望一個沒有數據的普通意圖。

以下是完整的錯誤:

IntentMatcher: has component: has component with: class name: is "com.shoeboxed.fetch.presentation.ui.activities.HomeActivity" package name: an instance of java.lang.String short class name: an instance of java.lang.String 

初步嘗試:

public class SplashActivityTest extends EspressoIntegrationTest { 

    @Mock 
    UserRepository userRepository; 

    @Rule 
    public IntentsTestRule<SplashActivity> activityRule = new IntentsTestRule<>(SplashActivity.class, true, false); 

    @Test 
    public void loggedInUser() { 
     User user = Fakes.user(); 
     when(userRepository.getUser()).thenReturn(user); 
     doNothing().when(userRepository).refreshTeam(); 

     activityRule.launchActivity(new Intent()); 
     intended(hasComponent(HomeActivity.class.getName())); 

     verify(userRepository, times(1)).getUser(); 
     verify(userRepository, times(1)).refreshTeam(); 
    } 
} 

第二次嘗試: (嘗試不同的匹配語法)

public class SplashActivityTest extends EspressoIntegrationTest { 

    @Mock 
    UserRepository userRepository; 

    @Rule 
    public IntentsTestRule<SplashActivity> activityRule = new IntentsTestRule<>(SplashActivity.class, true, false); 

    @Test 
    public void loggedInUser() { 
     User user = Fakes.user(); 
     when(userRepository.getUser()).thenReturn(user); 
     doNothing().when(userRepository).refreshTeam(); 

     activityRule.launchActivity(new Intent()); 
     intended(hasComponent(new ComponentName(getTargetContext(), HomeActivity.class))); 

     verify(userRepository, times(1)).getUser(); 
     verify(userRepository, times(1)).refreshTeam(); 
    } 
} 

第三次嘗試 (目的地活動添加空轉資源)

public class SplashActivityTest extends EspressoIntegrationTest { 

    @Mock 
    UserRepository userRepository; 

    @Rule 
    public IntentsTestRule<SplashActivity> activityRule = new IntentsTestRule<>(SplashActivity.class, true, false); 

    @Test 
    public void loggedInUser() { 
     User user = Fakes.user(); 
     when(userRepository.getUser()).thenReturn(user); 
     doNothing().when(userRepository).refreshTeam(); 

     WaitActivityIsResumedIdlingResource resource = new WaitActivityIsResumedIdlingResource(HomeActivity.class.getName()); 
     Espresso.registerIdlingResources(resource); 

     activityRule.launchActivity(new Intent()); 
     intended(hasComponent(new ComponentName(getTargetContext(), HomeActivity.class))); 

     verify(userRepository, times(1)).getUser(); 
     verify(userRepository, times(1)).refreshTeam(); 
     Espresso.unregisterIdlingResources(resource); 
    } 


    private static class WaitActivityIsResumedIdlingResource implements IdlingResource { 
     private final ActivityLifecycleMonitor instance; 
     private final String activityToWaitClassName; 
     private volatile ResourceCallback resourceCallback; 
     boolean resumed = false; 
     public WaitActivityIsResumedIdlingResource(String activityToWaitClassName) { 
      instance = ActivityLifecycleMonitorRegistry.getInstance(); 
      this.activityToWaitClassName = activityToWaitClassName; 
    } 

    @Override 
    public String getName() { 
     return this.getClass().getName(); 
    } 

    @Override 
    public boolean isIdleNow() { 
     resumed = isActivityLaunched(); 
     if(resumed && resourceCallback != null) { 
      resourceCallback.onTransitionToIdle(); 
     } 

     return resumed; 
    } 

    private boolean isActivityLaunched() { 
     Collection<Activity> activitiesInStage = instance.getActivitiesInStage(Stage.RESUMED); 
     for (Activity activity : activitiesInStage) { 
      if(activity.getClass().getName().equals(activityToWaitClassName)){ 
       return true; 
      } 
     } 
     return false; 
    } 

    @Override 
    public void registerIdleTransitionCallback(IdlingResource.ResourceCallback resourceCallback) { 
     this.resourceCallback = resourceCallback; 
    } 
} 

這是我的基礎測試。它在我的後臺進程(清潔建築用例)註冊一個空閒資源:

public class EspressoIntegrationTest { 

    private static IdlingResource idlingThreadPool; 

    private AppComponent oldComponent = app().appComponent(); 

    @Rule 
    public DaggerMockRule<AppComponent> daggerRule = new DaggerMockRule<>(AppComponent.class, new AppModule(app())) 
      .set(component -> { 
       oldComponent = app().appComponent(); 
       app().setAppComponent(component); 
      }); 

    @BeforeClass 
    public static void registerResources() { 
     idlingThreadPool = getIdlingThreadExecutor(); 
     Espresso.registerIdlingResources(idlingThreadPool); 
    } 

    @AfterClass 
    public static void deregister() { 
     Espresso.unregisterIdlingResources(idlingThreadPool); 
    } 

    @After 
    public void resetApp() { 
     app().setAppComponent(oldComponent); 
    } 

    private static IdlingResource getIdlingThreadExecutor() { 
     return (IdlingResource) jobExecutor().getThreadPoolExecutor(); 
    } 

    private static JobExecutor jobExecutor() { 
     return ((JobExecutor) app().appComponent().threadExecutor()); 
    } 

    private static App app() { 
     return (App) getInstrumentation().getTargetContext().getApplicationContext(); 
    } 
} 
+0

該解決方案:

所以,你可以使用ActivityTestRule和開展活動,這樣之前調用Intents.init()。 https://stackoverflow.com/a/36626564/3746714 – Diogosq

+0

這個使用閒置資源的解決方案適用於我。 https://stackoverflow.com/a/36626564/3746714 – Diogosq

回答

4

Asserts that the given matcher matches one and only one intent sent by the application under test. This is an equivalent of verify(mock, times(1)) in Mockito. Verification does not have to occur in the same order as the intents were sent. Intents are recorded from the time that Intents.init is called

See documentation

當您使用活動創建後IntentsTestRuleIntents.init()將complated。據我所知,你開始HomeActivitySplashActivity.onCreate並完成SplashActivity。利用空閒資源爲我工作

public class SplashActivityTest extends EspressoIntegrationTest { 

    @Mock 
    UserRepository userRepository; 

    @Rule 
    public ActivityTestRule<SplashActivity> activityRule = new ActivityTestRule<>(SplashActivity.class, true, false); 


    @Before 
    public void setUp() throws Exception{ 
     Intents.init(); 
    } 

    @Test 
    public void loggedInUser() { 
     User user = Fakes.user(); 
     when(userRepository.getUser()).thenReturn(user); 
     doNothing().when(userRepository).refreshTeam(); 

     activityRule.launchActivity(new Intent()); 
     intended(hasComponent(HomeActivity.class.getName())); 

     verify(userRepository, times(1)).getUser(); 
     verify(userRepository, times(1)).refreshTeam(); 
    } 


    @After 
    public void tearDown() throws Exception{ 
     Intents.release(); 
    } 
} 
+0

如果仍然出現錯誤,請嘗試使用'WaitActivityIsResumedIdlingResource' –

相關問題