How to get a view from within Espresso to pass into an IdlingResource?

后端 未结 4 1987
无人及你
无人及你 2021-01-03 20:59

I essentially have a custom IdlingResource that takes a View a constructor argument. I can\'t find anywhere that really talks about how to implemen

相关标签:
4条回答
  • 2021-01-03 21:14

    I haven't already used IdilingResources in Espresso, but did you saw these articles:

    • Espresso: Custom Idling Resource by Chiuki
    • Wait for it...a deep dive into Espresso's Idling Resources

    Also please check official Android Docs: Idling Resources (reference)

    To answer your question,

    • the best way to do it is passing in an instance of one of the Views into the class's constructor. Check: Calling findViewById() from outside an activity

    • another way is getting view by context. Check android - How to get view from context?

    Here's an exmple taken from a link above:

    Starting with a context, the root view of the associated activity can be had by

    View rootView = ((Activity)_context).Window.DecorView.FindViewById(Android.Resource.Id.Content);
    

    In Raw Android it'd look something like:

    View rootView = ((Activity)mContext).getWindow().getDecorView().findViewById(android.R.id.content)
    

    Then simply call the findViewById on this

    View v = rootView.findViewById(R.id.your_view_id);
    

    This might be also useful: How to call getResources() from a class which has no context?

    Hope it help

    0 讨论(0)
  • 2021-01-03 21:20

    Figured it out. To get the view to pass into an idling resource, all you have to do is take the member variable of your ActivityTestRule

    For example:

    @Rule
    public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(
            MainActivity.class);
    

    and then just call getActivity().findViewById(R.id.viewId)

    So the end result is:

    activityTestRule.getActivity().findViewById(R.id.viewId);
    
    0 讨论(0)
  • 2021-01-03 21:21

    If you are using ActivityScenarioRule from androidx.test.ext.junit.rules (since ActivityTestRule "will be deprecated and eventually removed from library in the future"), you can get your Activity instance and call findViewById method:

    import androidx.test.ext.junit.rules.activityScenarioRule
    import androidx.test.ext.junit.runners.AndroidJUnit4
    
    @RunWith(AndroidJUnit4::class) {
    
        @get: Rule
        var testRule = activityScenarioRule<MainActivity>()
    
        @Test
        fun mainTestCase() {
            testRule.scenario.onActivity { activity ->
                val view = activity.findViewById<YourView>(R.id.view)
            }
        }
    }
    
    
    0 讨论(0)
  • 2021-01-03 21:25

    The accepted answer works as long as a test is running in the same activity. However, if the test navigates to another activity activityTestRule.getActivity() will return the wrong activity (the first one). To address this, one can create a helper method returning an actual activity:

    public Activity getCurrentActivity() {
        final Activity[] currentActivity = new Activity[1];
        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                Collection<Activity> allActivities = ActivityLifecycleMonitorRegistry.getInstance()
                        .getActivitiesInStage(Stage.RESUMED);
                if (!allActivities.isEmpty()) {
                    currentActivity[0] = allActivities.iterator().next();
                }
            }
        });
        return currentActivity[0];
    }
    

    And then it could be used as the following:

    Activity currentActivity = getCurrentActivity();
    if (currentActivity != null) {
        currentActivity.findViewById(R.id.viewId);
    }
    
    0 讨论(0)
提交回复
热议问题