3

I am new to Espresso, and trying to write a test on a fragment that makes a Retrofit call when it is instantiated. When the call is received, I want to check the fragment to see if a view exists. I'm using an IdlingResource for the fragment and setting up a listener to be called that transitions the ResourceCallback to idle when the response is received (followed some steps in the implementation here: https://stackoverflow.com/a/30820189/4102823).

My fragment is instantiated when the user logs in and starts up MainActivity. The problem is that I just don't think my IdlingResource is set up correctly, and I don't know what's wrong with it. It is not even constructed until after the fragment is initiated and the call is made, even though I'm registering the IdlingResource in the test's setUp() method before everything else. So, I think the main issue here is how I get the IdlingResource instantiated alongside the fragment when I run the test, not after it. Could the problem be in the @Rule? Does it start MainActivity (which creates a NewsfeedFragment instance) before the test can run on the fragment? If so, how would I use a rule with my fragment instead?

Here is my fragment:

public ProgressListener mProgressListener;
public boolean mIsProgressShown = true;

public interface ProgressListener {
    void onProgressShown();
    void onProgressDismissed();
}

public void setProgressListener(ProgressListener progressListener) {
    mProgressListener = progressListener;
}

public NewsfeedFragment() {
}

public static NewsfeedFragment newInstance() {
    return new NewsfeedFragment();
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    OSUtil.setTranslucentStatusBar(getActivity().getWindow(), this.getContext());
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    mRootView = (SwipeRefreshLayout) inflater.inflate(R.layout.fragment_newsfeed, container, false);
    mNewsfeedFramelayout = (FrameLayout) mRootView.findViewById(R.id.newsfeed_framelayout);
    mProgressView = (ProgressBar) mRootView.findViewById(R.id.newsfeed_progress);
    mPageIndictorView = (FrameLayout) mRootView.findViewById(R.id.page_indicator);
    mPageIndicator = (TextView) mRootView.findViewById(R.id.page_indicator_text);
    mRootView.setOnRefreshListener(this);

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) mRootView.findViewById(R.id.newsfeed_viewpager);
    mPageChangeListener = this;

    if (savedInstanceState != null) {
        mTabPosition = savedInstanceState.getInt(EXTRA_TAB_POSITION);
        mViewPager.setCurrentItem(mTabPosition);
    }

    fetchNewsFeed();

    return mRootView;
}

private void fetchNewsFeed() {
    if (NetworkUtils.isConnectedToInternet(getActivity())) {
        if (NetworkUtils.getService() != null) {
            if (mRootView.isRefreshing()) {
                dismissProgress();
            } else {
                showProgress();
            }
            showProgress();

            Call<Newsfeed> call = NetworkUtils.getService().getNewsfeed();
            call.enqueue(new Callback<Newsfeed>() {
                @Override
                public void onResponse(Call<Newsfeed> call, Response<Newsfeed> response) {
                    if (response.isSuccessful()) {

                        dismissProgress();
                        mNewsfeed = response.body();
                        FragmentManager fragmentManager = getChildFragmentManager();
                        mNewsfeedPagerAdapter = new NewsfeedPagerAdapter(fragmentManager, mNewsfeed.getNewsfeedItems());
}

...


    private void showProgress() {
        // show the progress and notify the listener
        if (mProgressListener != null){
            setProgressIndicatorVisible(true);
            notifyListener(mProgressListener);
        }
    }

    public void dismissProgress() {
        // hide the progress and notify the listener
        if (mProgressListener != null){
            setProgressIndicatorVisible(false);
            mIsProgressShown = false;
            notifyListener(mProgressListener);
        }
    }

    public boolean isInProgress() {
        return mIsProgressShown;
    }

    private void notifyListener(ProgressListener listener) {
        if (listener == null){
            return;
        }
        if (isInProgress()){
            listener.onProgressShown();
        }
        else {
            listener.onProgressDismissed();
        }
    }

Here is the IdlingResource:

public class ProgressIdlingResource implements IdlingResource, NewsfeedFragment.ProgressListener {

private ResourceCallback mResourceCallback;
private NewsfeedFragment mNewsfeedFragment;


public ProgressIdlingResource(NewsfeedFragment fragment) {
    mNewsfeedFragment = fragment;
    mNewsfeedFragment.setProgressListener(this);
}

@Override
public String getName() {
    return "ProgressIdlingResource";
}

@Override
public boolean isIdleNow() {
    return !mNewsfeedFragment.mIsProgressShown;
}

@Override
public void registerIdleTransitionCallback(ResourceCallback callback) {
    mResourceCallback = callback;
}

@Override
public void onProgressShown() {

}

@Override
public void onProgressDismissed() {
    if (mResourceCallback == null) {
        return;
    }
    //Called when the resource goes from busy to idle.
    mResourceCallback.onTransitionToIdle();
}
}

The fragment test:

public class NewsfeedFragmentTest {
@Before
public void setUp() throws Exception {
    Espresso.registerIdlingResources(new ProgressIdlingResource((NewsfeedFragment) MainActivity.getCurrentFragment()));
}

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

@Test
public void getViewPager() throws Exception {
    onView(allOf(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE),
            withId(R.id.newsfeed_viewpager))).check(matches(isDisplayed()));
}

@Test
public void getNewsfeedItems() throws Exception {
    onView(withId(R.id.page_indicator)).check(matches(isDisplayed()));
}

}

Community
  • 1
  • 1
TonyKazanjian
  • 269
  • 2
  • 13

1 Answers1

3

Retrofit is using OkHttp, and there is a standard way to setup IdlingResource for that matter. Refer to OkHttp IdlingResource

WenChao
  • 3,586
  • 6
  • 32
  • 46
  • if you looking sample tutorial for aforementioned check this https://wajahatkarim.com/2018/06/idling-registry-for-okhttp/ – Sam Apr 11 '19 at 04:13