Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I test an interface implemented by an Activity which is used by a fragment?

I have an Activity that contains two fragments. One fragment has a EditText and a Button; when the button is clicked, a callback is invoked with the text from the edit box:

// Not showing implementation of onCreateView()
class HelloEditFragment extends Fragment implements View.OnClickListener {
  interface OnListener {
    void onValue(String value);
  }

  private OnListener mListener;

  public void onAttach(Context context) {
    mListener = (OnListener) context;
  }

  public void onClick(View v) {
    mListener.onValue(mEditText.getText().toString();
  }
}

My Activity implements OnListener:

class HelloActivity extends Activity implements HelloEditFragment.OnListener {
  public void onValue(String value) {
    // ...
  }
}

So far my test looks like this:

@RunWith (AndroidJUnit4.class)
public class HelloEditFragmentTest {

  @Rule
  public ActivityTestRule<HelloActivity> mActivityRule = new ActivityTestRule<> (HelloActivity.class);

  @Test
  public void testActivity () {
    onView (withId (R.id.edit_text_hello_edit)).perform (typeText ("hello"));
    onView (withId (R.id.button_hello_edit)).perform (click ());
    // Now what?
  }
}

How can I check that the onValue() callback is called when the button in the fragment is clicked? Thanks,

like image 214
piwi Avatar asked Oct 18 '25 03:10

piwi


1 Answers

There won't be an easy way to do that. I would suggest you give up on having the interface implemented by the Activity and use a field Listener instead.

E.g. like this:

class HelloActivity extends Activity {

    HelloEditFragment.OnListener listener = new HelloEditFragment.OnListener() {
        @Override
        public void onValue(String value) {
            // ...
        }
    };

    public HelloEditFragment.OnListener getListener() {
        return listener;
    }

    //... everything else
}

class HelloEditFragment extends Fragment implements View.OnClickListener {

    public void onAttach(Context context) {
        if (context instanceof HelloActivity) {
            mListener = ((HelloActivity) context).getListener();
        }
    }

    //... everything else (including onDetach with clearing the listener)
}

And then you can easily mock your field listener:

@RunWith (AndroidJUnit4.class)
public class HelloEditFragmentTest {

    @Rule
    public ActivityTestRule<HelloActivity> mActivityRule = new ActivityTestRule<> (HelloActivity.class);

    @Test
    public void testActivity () {
        HelloEditFragment.OnListener listener = Mockito.mock(HelloEditFragment.OnListener.class);
        mActivityRule.getActivity().listener = listener;

        onView (withId (R.id.edit_text_hello_edit)).perform (typeText ("hello"));
        onView (withId (R.id.button_hello_edit)).perform (click ());

        Mockito.verify(listener, Mockito.times(1)).onValue("hello");
        Mockito.verifyNoMoreInteractions(listener);
    }
}
like image 58
Bartek Lipinski Avatar answered Oct 20 '25 17:10

Bartek Lipinski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!