Espresso 测试失败:想要匹配 1 个意图。实际匹配 0 个意图

2024-01-19

我正在尝试测试如果用户登录,我的 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();
    }
}

断言给定的匹配器与被测应用程序发送的一个且仅一个意图匹配。这相当于 Mockito 中的 verify(mock, ti​​mes(1))。验证不必按照发送意图的顺序进行。Intents从调用Intents.init时开始记录

查看文档 https://developer.android.com/reference/android/support/test/espresso/intent/Intents.html#intended(org.hamcrest.Matcher%3Candroid.content.Intent%3E)

当你使用IntentsTestRule Intents.init()将在活动创建后完成。据我了解,你开始HomeActivity in SplashActivity.onCreate并完成SplashActivity.

所以你可以使用ActivityTestRule并打电话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();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Espresso 测试失败:想要匹配 1 个意图。实际匹配 0 个意图 的相关文章

随机推荐