Testing an isolated fragment outside of its production activity with Robolectric 2.2

2,858 views
Skip to first unread message

Dietrich Schulten

unread,
Dec 19, 2013, 11:08:53 AM12/19/13
to robol...@googlegroups.com, sae...@gmx.net
Hi,

in our Robolectric 1.1 tests we frequently tested Fragments in isolation. We created a simple base activity and used it only as host for the fragment under test. For this, the activity instance is needed because it provides a fragment manager where we can add our fragment under test.

With the ActivityController, this is no longer possible. In order to get an activity instance with clickable (visible) views, we must call visible() after the views are completely inflated into the activity's root view. After we call get(), we can use the instance's fragment manager to add the fragment, but getView() of the fragment returns null.
Is there a recommendation how to test fragments in isolation? Or is this no longer a supported practice?

Best regards,
Dietrich

Mike Grafton

unread,
Dec 20, 2013, 12:04:28 AM12/20/13
to robol...@googlegroups.com, sae...@gmx.net
Hi Dietrich,

You should still be able to test Fragments in isolation (ish). I don't have access to any code that does this right now, but I've done it recently.  I've never tried to use getView(), and maybe there's a problem with Robolectric and that method. I've always just used activity.findViewById(). 

You still need to do what you say - create a host Activity and use ActivityController to drive it (the Activity and thus the Fragment) through lifecycle steps. A real FragmentManager will be in play and will do the right thing (mostly). I think you can create a TestActivity class and in the onCreate() method call setContentView() before adding the fragment with a FragmentTransaction. You can use 'new LinearLayout()'  and pass that to setContentView().

Let me know if this doesn't work. I have a colleague who has access to some source code to verify this is the technique we used.

Mike




--
You received this message because you are subscribed to the Google Groups "Robolectric" group.
To unsubscribe from this group and stop receiving emails from it, send an email to robolectric...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Dietrich Schulten

unread,
Dec 20, 2013, 2:46:07 AM12/20/13
to robol...@googlegroups.com, sae...@gmx.net
On StackOverflow someone had a similar problem: http://stackoverflow.com/questions/16179675/robolectric-how-can-i-test-an-activity-that-contains-a-sherlockfragment. It seems, one must add attach() to the initialization list of the test activity:

Robolectric.buildActivity(YourActivityClass.class).attach().create().start().resume().get();

That view, the fragment's onCreateView is called and things seem to work from there.

Mike Grafton

unread,
Dec 21, 2013, 12:59:15 AM12/21/13
to robol...@googlegroups.com
Hmmm, I verified with my colleague that we didn't need to call attach(). We called .create() on the ActivityController, and then we actually attached the fragment in the test code by calling activity.getFragmentManager() and committing a FragmentTransaction. After that we were able to use fragment.getView().findViewById().

It's a mystery to me why getView() would be returning null for you. The FragmentManager should be calling onCreateView() as soon as the fragment is added.

Mike
Message has been deleted

Dietrich Schulten

unread,
Dec 23, 2013, 3:52:05 AM12/23/13
to robol...@googlegroups.com
We were successful to test fragments and views in isolation by using a special TestFragmentActivity extending FragmentActivity as host.
The following was necessary to get clickable views in fragments and views

final TestActivity activity = Robolectric.buildActivity( TestActivity.class ).create().visible().get();

The TestActivity must create and set a framelayout with a known parent id in its onCreate method:

   public static final int PARENT_VIEW_ID = 1;

   @Override
   protected void onCreate( final Bundle savedInstanceState )
   {
      super.onCreate( savedInstanceState );
      final FrameLayout frameLayout = new FrameLayout( this );
      frameLayout.setId( PARENT_VIEW_ID );
      setContentView( frameLayout );
   }     

Use the id when adding the fragment:

activity.getSupportFragmentManager()
         .beginTransaction()
         .add( TestActivity.PARENT_VIEW_ID, fragment, null )
         .commit();
     
In order to test views in isolation, add them to the activity like this:     

      final LayoutInflater layoutInflater = LayoutInflater.from( activity );
      final View viewUnderTest = layoutInflater.inflate( R.layout.view_under_test, null );
      final LayoutParams params = new ViewGroup.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT );
      activity.addContentView( viewUnderTest, params );
     
That will give you visible buttons etc. when using activity.findViewById.     
Reply all
Reply to author
Forward
0 new messages