I have a test that is supposed to test the visibility of an error msg when there is no network connection, but I dunno how to get it to show?
@RunWith(AndroidJUnit4.class)
@LargeTest
public class PostsActivityTest {
@Rule
public final ActivityRule<PostsActivity> rule = new ActivityRule<>(PostsActivity.class);
PostsActivity postsActivity;
@Before
public void init() {
postsActivity = rule.get();
}
@Test
public void testShouldShowErrorViewOnNetworkError() {
postsActivity.showErrorMsg(); // doesn't work
onView(withId(R.id.error_view)).check(matches(isDisplayed()));
}
When calling postsActivity.showErrorMsg();
I get a crash stating android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
This is the showErrorMsg()
in PostsActivity
:
public void showErrorMsg() {
errorView.setVisibility(View.VISIBLE);
}
Any help appreciated. Thanks!
Edit: Using runOnUiThread
seems to be working. I dunno if this is the preferred way though.
@Test
public void testShouldShowErrorViewOnNetworkError() {
postsActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
postsActivity.showErrorMsg();
}
});
onView(withId(R.id.error_view)).check(matches(isDisplayed()));
}
Espresso is an open source android user interface (UI) testing framework developed by Google. The term Espresso is of Italian origin, meaning Coffee. Espresso is a simple, efficient and flexible testing framework.
One simple way to check for a View or its subclass like a Button is to use method getVisibility from View class. I must caution that visibility attribute is not clearly defined in the GUI world. A view may be considered visible but may be overlapped with another view, for one example, making it hidden.
The basic idea is to use a method with an internal ViewAction that retrieves the text in its perform method. Anonymous classes can only access final fields, so we cannot just let it set a local variable of getText() , but instead an array of String is used to get the string out of the ViewAction .
In your Espresso
tests you should not directly call methods of your Activity
. You should use Espresso
to interact with the UI like a real user.
runOnUiThread
is required:When running instrumentation tests (e.g. Espresso
tests) there are actually two apps involved. First the app that is being tested and the app that executes the tests. Both use different main threads.
If you call PostsActivity#showErrorMsg
from your test, it is running in the testing apps thread. But manipulating views in Android is only allowed from the apps UI Thread. If you really have to call PostsActivity#showErrorMsg
from your test, runOnUiThread
is the right choice.
So instead of calling PostsActivity#showErrorMsg
directly from your test, use Espresso
to click()
e.g. on a Button
that will call that method for you:
@Test
public void testShouldShowErrorViewOnNetworkError() {
onView(withId(R.id.post_button)).perform(click());
onView(withId(R.id.error_view)).check(matches(isDisplayed()));
}
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