Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the activity reference before its oncreate gets called during testing

How to get the reference of Activity before its onCreate will be called. while its under test. I use ActivityTestRule as JUnit Rule. The reason for this requirement is i want to inject Mocks into activity from tests.

public class MyActivity extends Activity{

    MyComponent myComponent;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        if(myComponent==null){
            myComponent ... //initialise dagger component
        }
        myComponent.inject(this);
        ...
    }

    public void setComponent(MyComponent comp){
        this.myComponent = comp;
    }
}

public class MyTest{

    @Rule
    public ActivityTestRule<MyActivity> intentsTestRule = new ActivityTestRule<>(MyActivity.class);


    MyComponent myFakeComponent;

    @Before                                      
    public void setUp() {                        
        MyActivity activity = intentsTestRule.getActivity();  
        activity.setComponent(myFakeComponent);
    }                                            

    @Test
    public void testMethod1(){...}
} 
like image 711
Rajesh Batth Avatar asked Jul 13 '15 16:07

Rajesh Batth


1 Answers

As per documentation, what you're doing here is wrong.

@Rule
public ActivityTestRule<MyActivity> intentsTestRule = new ActivityTestRule<>(MyActivity.class);

MyComponent myFakeComponent;

@Before                                      
public void setUp() {                        
    MyActivity activity = intentsTestRule.getActivity();  
    activity.setComponent(myFakeComponent);
}              

Because,

This rule provides functional testing of a single activity. The activity under test will be launched before each test annotated with Test and before methods annotated with @Before. It will be terminated after the test is completed and methods annotated with After are finished. During the duration of the test you will be able to manipulate your Activity directly.

However!

protected void beforeActivityLaunched ()

Override this method to execute any code that should run before your Activity is created and launched. This method is called before each test method, including any method annotated with @Before.

Therefore, if you move the initialization of the MainActivityComponent outside the Activity to a place that is mockable, then you'll be able to tinker it together before the main activity is created.

EDIT:

Another possible solution is to lazily initiate the Activity as per link.

@Rule
public ActivityTestRule<NoteDetailActivity> mNoteDetailActivityTestRule =
        new ActivityTestRule<>(NoteDetailActivity.class, true /* Initial touch mode  */,
                false /* Lazily launch activity */);

@Before
public void intentWithStubbedNoteId() {
   // Add a note stub to the fake service api layer.
   FakeNotesServiceApiImpl.addNotes(NOTE);

   // Lazily start the Activity from the ActivityTestRule this time to inject the start Intent
   Intent startIntent = new Intent();
   startIntent.putExtra(NoteDetailActivity.EXTRA_NOTE_ID, NOTE.getId());
   mNoteDetailActivityTestRule.launchActivity(startIntent);

   registerIdlingResource();
}
like image 179
EpicPandaForce Avatar answered Nov 11 '22 21:11

EpicPandaForce