意式浓缩咖啡测试失败:希望匹配1个意图。其实匹配0意图

问题描述:

我想测试我的SplashActivity正确启动HomeActivity如果用户登录。意式浓缩咖啡测试失败:希望匹配1个意图。其实匹配0意图

我已经看过*上相关的问题,这似乎是一个常见的问题,但我似乎无法得到任何东西工作。

我已经看过测试在我的设备上执行,并通过视觉验证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://*.com/a/36626564/3746714 – Diogosq

+0

这个使用闲置资源的解决方案适用于我。 https://*.com/a/36626564/3746714 – Diogosq

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' –