I'm writing Espresso tests for an app written using Conductor. I'd like to specify which controller to start for each test, so that I don't need to get Espresso to click through the app from the beginning Activity for each. Since there is only one Activity and not much on SO or google about Conductor the closest I could find was this question? Or is this not possible?
I've tried making the router static and adding a getter in an attempt to set a specific root for testing with no success.
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
In MainActivity:
public static Router getRouter() {
return router;
}
In Instrumentation Test:
@Rule
public ActivityTestRule<MainActivity> testRule = new ActivityTestRule<>(MainActivity.class);
@Before
public void setUp() {
Router router = testRule.getActivity().getRouter();
router.setRoot(RouterTransaction.with(new ControllerIwantToTest()));
}
@Test
public void titleIsDisplayed() {
onView(withText("My Controllers Title")).check(matches(isDisplayed()));
}
Instrumented tests run on Android devices, whether physical or emulated. As such, they can take advantage of the Android framework APIs. Instrumented tests therefore provide more fidelity than local tests, though they run much more slowly.
If anyone else comes across the same issue, I've solved the problem by doing the following:
@RunWith(AndroidJUnit4.class)
public class NoBundleControllerEspressoTest {
private Router router;
@Rule
public ActivityTestRule<NoBundleConductorActivity> testRule = new ActivityTestRule<>(NoBundleConductorActivity.class);
@Before
public void setUp() {
Activity activity = testRule.getActivity();
activity.runOnUiThread(() -> {
router = testRule.getActivity().getRouter();
router.setRoot(RouterTransaction.with(new NoBundleController()));
});
}
@Test
public void titleIsDisplayed() {
onView(withText("Super Awesome Title")).check(matches(isDisplayed()));
}
}
Or if your controller uses a Bundle
in it's contructor as most of our do:
@RunWith(AndroidJUnit4.class)
public class BundleControllerEspressoTest {
private Router router;
private ControllerBundleData controllerData;
@Rule
public ActivityTestRule<BundleConductorActivity> testRule = new ActivityTestRule<>(BundleConductorActivity.class);
@Before
public void setUp() {
controllerData = new ControllerBundleData();
Bundle bundle = new Bundle();
bundle.putSerializable(YOUR_BUNDLE_KEY, controllerData);
Activity activity = testRule.getActivity();
activity.runOnUiThread(() -> {
router = testRule.getActivity().getRouter();
router.setRoot(RouterTransaction.with(new BundleController(bundle)));
});
}
@Test
public void titleIsDisplayed() {
onView(withText("Super Awesome Title")).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