浓咖啡测试失败:想要匹配1个意图.实际匹配的0个意图 [英] Espresso Test Failed: Wanted to match 1 intents. Actually matched 0 intents

查看:57
本文介绍了浓咖啡测试失败:想要匹配1个意图.实际匹配的0个意图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果用户已登录,我试图测试我的SplashActivity是否正确启动HomeActivity.

I am trying to test that my SplashActivity correctly launches HomeActivity if the user is logged in.

我已经查看了StackOverflow上的相关问题,这似乎是一个常见问题,但是我似乎无法解决任何问题.

I have looked at related questions on StackOverflow, this seems to be a common issue, but I just cannot seem to get anything to work.

我已经看到测试在我的设备上执行,并通过视觉验证了SplashActivity确实正在启动HomeActivity.

I have watched the test execute on my device and visually verified that SplashActivity is indeed launching HomeActivity.

HomeActivity期望一个没有数据的简单意图.

HomeActivity expects a plain intent with no data.

这是完整的错误:

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();
    }
}

第二次尝试: (尝试不同的匹配语法)

Second Attempt: (Trying different matching syntax)

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();
    }
}

第三次尝试 (在目标活动上添加空闲资源)

Third Attempt (Adding an Idling Resource on the destination 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;
    }
}

这是我的基本测试.它将空闲资源注册到我的后台进程中(干净的体系结构用例):

Here is my base test. It registers an idling resource on my background processes (clean architecture use cases):

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,times(1)).验证不必按照发送意图的相同顺序进行. 从调用Intents.init的时间开始记录意图.

使用IntentsTestRuleIntents.init()将在创建活动后进行编译.据我了解,您从SplashActivity.onCreate开始HomeActivity并完成SplashActivity.

When you use IntentsTestRule Intents.init() will complated after activity created. As far as I understand, you starting HomeActivity in SplashActivity.onCreate and finish SplashActivity.

因此,您可以在启动活动之前使用ActivityTestRule并致电Intents.init(),例如:

So you can use ActivityTestRule and call Intents.init() before launching activity, like this:

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();
    }
}

这篇关于浓咖啡测试失败:想要匹配1个意图.实际匹配的0个意图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆