我正在尝试测试如果用户登录,我的 SplashActivity 是否可以正确启动 HomeActivity。
我查看了 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();
}
}