I'm creating and Android Application. I'm using Espresso for testing.
I've an Activity with the method:
public void render(Recipe recipe){
//draw the recipe to the activity
}
I want to test that this method works correctly.
Not working solution 1
I've tested the following
@Test
public void viewPaintsRecipes() {
final Activity activity = activityRule.launchActivity(new Intent());
((MainActivity)activity).render(Arrays.asList(new Recipe[]{recipe}));
onView(withId(R.id.text)).check(matches(withText(recipe.toString())));
}
I get an Exception.
Only the original thread that created a view hierarchy can touch its views.
Not working solution 2
I've also tried to put the two lines inside a runnable runned by a Handler in the main thread, but the test hangs.
How can I acchieve this?
Notes
I attach the full test. Note that I use dagger and Mockito too.
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTestWithMockPresenter {
Recipe recipe = new Recipe("sampleTitle");
@Rule
public ActivityTestRule<MainActivity> activityRule = new ActivityTestRule(MainActivity.class, true, false);
@Mock
MainActivityPresenter mockPresenter;
@Mock
AndroidApplication mockContext;
@Before
public void insertMockedComponent(){
MockitoAnnotations.initMocks(this);
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
AndroidApplication app = (AndroidApplication) instrumentation.getTargetContext().getApplicationContext();
MyModule mockedMyModule = new MyModule(mockContext){
@Provides
public MainActivityPresenter getMainActivityPresenter(){
return mockPresenter;
}
};
MyComponent component = DaggerMyComponent.builder().myModule(mockedMyModule).build();
app.setComponent(component);
}
@Test
public void viewPaintsRecipes() {
final Activity activity = activityRule.launchActivity(new Intent());
((MainActivity)activity).render(Arrays.asList(new Recipe[]{recipe}));
onView(withId(R.id.text)).check(matches(withText(recipe.toString())));
}
}
Thanks
This answer previously demonstrated how to call a method on the Activity
under test by means of the ActivityTestRule.runOnUiThread(Runnable)
method as follows:
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
@get:Rule var activityTestRule = ActivityTestRule(MainActivity::class.java)
@Test
fun recipe_is_rendered() {
// When.
activityTestRule.runOnUiThread { activityTestRule.activity.render(someRecipe) }
// Then.
// assert stuff about the recipe rendering here
}
}
The ActivityTestRule class has since been deprecated and replaced by the ActivityScenarioRule class. The new, preferred way to call a method on the Activity
under test is by means of the ActivityScenario.onActivity(ActivityAction)
method as follows:
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
@get:Rule var activityScenarioRule = ActivityScenarioRule(MainActivity::class.java)
@Test
fun recipe_is_rendered() {
// When.
activityScenarioRule.scenario.onActivity { it.render(someRecipe) }
// Then.
// assert stuff about the recipe rendering here
}
}
The only two dependencies I needed to add to my build.gradle
file to do this were the following:
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With