Reputation: 1662
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(){...}
}
Upvotes: 10
Views: 8283
Reputation: 1154
Here is my sample code for that:
public class TestClass {
@Rule
public ActivityTestRule<T> activityRule = new ActivityTestRule<T>(type) {
@Override
protected void beforeActivityLaunched() {
//TODO inject mocks, setup stubs etc..
}
};
}
@Before
public void before() {
activityRule.getActivity();
}
@Test
public void myTest() {
//...
}
}
Upvotes: 1
Reputation: 81588
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();
}
Upvotes: 19
Reputation: 437
Is this code complete? I can't see you creating the dagger graph. Anyway, what I do in my code, is to have a Static class called Injector that creates the graph for me, and also can inject elements into objects. So, in my Application Class I call it to create the graph, and all other activities just use the existent graph.
Then, in a test, you could create a fake test application class that initialize the graph in a different way, or simply recreate the graph calling the Injector methods, before the activity is created. I'm not familiar with ActivityTestRule, so I can't help much with the life cycle of this test.
But just make sure you create a new graph before the activity is created, and let the activity just use the existent graph. How the activity access the graph? Well, I don't really love it, but we are used to access the application class (with explicit cast) and ask it to inject the dependencies for us. This is the way Dagger examples do it also.
Upvotes: 0