I have yet to dive deep into what causes this, but here is a side effect I have observed with Espresso assertions running in a JUnit 5 context that uses RobolectricExtension
. It's probably the magic of switching thread contexts and class loaders that trips it up, but I wanted to hear your thoughts on the matter first. If I remove the Espresso stuff and only keep ActivityScenario
around, then it seems to work no matter how many tests I run. Also, this happens with any kind of test (@ParameterizedTest
, @RepeatedTest
etc), but I am using the base @Test
to make it as simple as possible.
With JUnit 5
The following test class will execute "test 1" successfully, then deadlock in "test 2" just before the first onView().check()
assertion:
// ...
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(RobolectricExtension::class)
class ActivityScenarioTest {
@Test
fun `test 1`() {
println("1")
val scenario = ActivityScenario.launch(MainActivity::class.java)
println(" - check")
onView(withText("Changed")).check(doesNotExist())
println(" - click")
onView(withText("Click me")).perform(click())
println(" - verify")
onView(withText("Changed")).check(matches(isDisplayed()))
scenario.close()
}
@Test
fun `test 2`() {
println("2")
val scenario = ActivityScenario.launch(MainActivity::class.java)
println(" - check")
onView(withText("Changed")).check(doesNotExist())
println(" - click")
onView(withText("Click me")).perform(click())
println(" - verify")
onView(withText("Changed")).check(matches(isDisplayed()))
scenario.close()
}
}
With JUnit 4
When changing this to a JUnit 4 environment (i.e. change @Test
annotations, then replace @ExtendWith
with @RunWith
), all tests are okay:
// ...
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class ActivityScenarioTest {
@Test
fun `test 1`() {
println("1")
val scenario = ActivityScenario.launch(MainActivity::class.java)
println(" - check")
onView(withText("Changed")).check(doesNotExist())
println(" - click")
onView(withText("Click me")).perform(click())
println(" - verify")
onView(withText("Changed")).check(matches(isDisplayed()))
scenario.close()
}
@Test
fun `test 2`() {
println("2")
val scenario = ActivityScenario.launch(MainActivity::class.java)
println(" - check")
onView(withText("Changed")).check(doesNotExist())
println(" - click")
onView(withText("Click me")).perform(click())
println(" - verify")
onView(withText("Changed")).check(matches(isDisplayed()))
scenario.close()
}
}
I have pushed an example to a branch in my fork: https://github.com/mannodermaus/junit5-robolectric-extension/blob/check/androidx-robolectric-espresso-deadlock/integration-tests/agp-kotlin-dsl/src/test/kotlin/tech/apter/junit/jupiter/robolectric/integration/tests/agp/kotlin/dsl/ActivityScenarioTest.kt