Espresso 测试失败:想要匹配 1 个意图。实际匹配 0 个意图
Espresso Test Failed: Wanted to match 1 intents. Actually matched 0 intents
我正在尝试测试我的 SplashActivity 在用户登录后是否正确启动 HomeActivity。
我查看了 Whosebug 上的相关问题,这似乎是一个常见问题,但我似乎无法解决任何问题。
我在我的设备上观察了测试执行情况,并通过视觉验证 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();
}
}
第三次尝试
(在目的地添加闲置资源 activity)
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();
}
}
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
当您使用IntentsTestRule
时,Intents.init()
将在activity创建后完成。据我了解,您在 SplashActivity.onCreate
开始 HomeActivity
并在 SplashActivity
.
结束
因此您可以使用 ActivityTestRule
并在启动 activity 之前调用 Intents.init()
,如下所示:
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();
}
}
我正在尝试测试我的 SplashActivity 在用户登录后是否正确启动 HomeActivity。
我查看了 Whosebug 上的相关问题,这似乎是一个常见问题,但我似乎无法解决任何问题。
我在我的设备上观察了测试执行情况,并通过视觉验证 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();
}
}
第三次尝试 (在目的地添加闲置资源 activity)
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();
}
}
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
当您使用IntentsTestRule
时,Intents.init()
将在activity创建后完成。据我了解,您在 SplashActivity.onCreate
开始 HomeActivity
并在 SplashActivity
.
因此您可以使用 ActivityTestRule
并在启动 activity 之前调用 Intents.init()
,如下所示:
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();
}
}