robolectric / robolectric

Android Unit Testing Framework
http://robolectric.org
Other
5.87k stars 1.36k forks source link

Robolectric doesn't support `@UiThreadTest` #9026

Open sunnygoyal opened 4 months ago

sunnygoyal commented 4 months ago

When migrating a test which was using AndroidJUnit4 to robolectric with looperMode = INSTRUMENTATION_TEST, @UiThreadTest annotations are ignored and the test runs doesn't run on the main thread

hoisie commented 4 months ago

cc @brettchabot

Are you using RobolectricTestRunner or AndroidJUnit4?

Also, which annotation are you referring to?

Is it this one:

https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/test-base/src/android/test/UiThreadTest.java

Or https://developer.android.com/reference/android/support/test/annotation/UiThreadTest?

Or the AndroidX one?

This annotation seems very specific to instrumentation tests, which does not really apply to RobolectricTestRunner. In Robolectric, test methods run on the UI thread by default, so supporting this annotation may be redundant.

if your tests need some specific behavior when @ UiThreadTest is present, you could try to extend RobolectricTestRunner and customize the behavior.

sunnygoyal commented 4 months ago

I am using AndroidJUnit4 which has been modified to automatically switch to RobolectricTestRunner based on the test environment. Also I am using androidx.test.annotation.UiThreadTest and the java doc for AndroidJUnit4 mentions that it is supported by default

Based on the recommended pattern for sharedTest, the behavior should be same on both environments (android and robolectric)

test methods run on the UI thread by default

this issue is specific to when using looperMode=INSTRUMENTATION_TEST in robolectric where the tests run on a background thread by default and there is a separate main thread

brettchabot commented 4 months ago

Unfortunately this is a known issue. Robolectric doesn't support UiThreadTest.

As a workaround, would posting the work to the main Looper be a workaround? eg

@Test
public void uiThreadTest() {
    getInstrumentation().runOnMainSync( ...
}
sunnygoyal commented 4 months ago

The above snipped doesn't work for @Before and @After blocks.

I was able to workaround it temporarily by defining a custom TestRule similar to UiThreadStatement and using some reflection code to figure out if the rest is running on android or in robolectric.

Though Ideally it should be implemented in the RobolectricTestRunner itself similar to AndroidJUnit4ClassRunner otherwise it breaks the sharedTest pattern