google / dagger

A fast dependency injector for Android and Java.
https://dagger.dev
Apache License 2.0
17.44k stars 2.02k forks source link

SecurityException when trying to run UI test with hilt and Jetpack Compose on Android 14 #4222

Closed tabatsky closed 9 months ago

tabatsky commented 9 months ago

I'm getting the following error:

java.lang.SecurityException: jatx.russianrocksongbook: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts at android.os.Parcel.createExceptionOrNull(Parcel.java:3057) at android.os.Parcel.createException(Parcel.java:3041) at android.os.Parcel.readException(Parcel.java:3024) at android.os.Parcel.readException(Parcel.java:2966) at android.app.IActivityManager$Stub$Proxy.registerReceiverWithFeature(IActivityManager.java:5684) at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1852) at android.app.ContextImpl.registerReceiver(ContextImpl.java:1792) at android.app.ContextImpl.registerReceiver(ContextImpl.java:1780) at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:755) at androidx.test.core.app.InstrumentationActivityInvoker$ActivityResultWaiter.(InstrumentationActivityInvoker.java:272) at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:409) at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:437) at androidx.test.core.app.ActivityScenario.launchInternal(ActivityScenario.java:265) at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:195) at androidx.test.ext.junit.rules.ActivityScenarioRule.lambda$new$0(ActivityScenarioRule.java:77) at androidx.test.ext.junit.rules.ActivityScenarioRule$$ExternalSyntheticLambda1.get(Unknown Source:2) at androidx.test.ext.junit.rules.ActivityScenarioRule.before(ActivityScenarioRule.java:110) at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:50) at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invoke(AndroidComposeTestRule.android.kt:272) at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1$evaluate$1.invoke(AndroidComposeTestRule.android.kt:271) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidComposeUiTestImpl.withDisposableContent(ComposeUiTest.android.kt:501) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1$1.invoke(ComposeUiTest.android.kt:333) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withComposeIdlingResource(ComposeUiTest.android.kt:385) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withComposeIdlingResource(ComposeUiTest.android.kt:219) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1$1.invoke(ComposeUiTest.android.kt:332) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withWindowRecomposer(ComposeUiTest.android.kt:359) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withWindowRecomposer(ComposeUiTest.android.kt:219) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1$1.invoke(ComposeUiTest.android.kt:331) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.withTestCoroutines(ComposeUiTest.android.kt:372) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$withTestCoroutines(ComposeUiTest.android.kt:219) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1$1.invoke(ComposeUiTest.android.kt:330) at androidx.compose.ui.test.EspressoLink.withStrategy(EspressoLink.android.kt:66) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1$1.invoke(ComposeUiTest.android.kt:329) at androidx.compose.ui.test.IdlingResourceRegistry.withRegistry(IdlingResourceRegistry.jvm.kt:155) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$runTest$1.invoke(ComposeUiTest.android.kt:328) at androidx.compose.ui.test.ComposeRootRegistry.withRegistry(ComposeRootRegistry.android.kt:146) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.runTest(ComposeUiTest.android.kt:327) at androidx.compose.ui.test.junit4.AndroidComposeTestRule$apply$1.evaluate(AndroidComposeTestRule.android.kt:271) at dagger.hilt.android.internal.testing.MarkThatRulesRanRule$1.evaluate(MarkThatRulesRanRule.java:108) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at org.junit.runner.JUnitCore.run(JUnitCore.java:115) at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:67) at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:58) at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:446) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2402)

tabatsky commented 9 months ago

Seems hilt-android-testing:2.50 depends on obsolete androidx.test:core:1.4.0, because when I'm trying to upgrade it to version 1.5.0, I'm getting the following error:

Could not resolve androidx.test:core:1.4.0. Required by: project :app > com.google.dagger:hilt-android-testing:2.50 Cannot find a version of 'androidx.test:core' that satisfies the version constraints: Dependency path 'RussianRockSongBook4:app:unspecified' --> 'androidx.test:core:1.5.0' Constraint path 'RussianRockSongBook4:app:unspecified' --> 'androidx.test:core:{strictly 1.4.0}' because of the following reason: debugRuntimeClasspath uses version 1.4.0 Dependency path 'RussianRockSongBook4:app:unspecified' --> 'androidx.test:core-ktx:1.5.0' (runtime) --> 'androidx.test:core:1.5.0' Dependency path 'RussianRockSongBook4:app:unspecified' --> 'androidx.test.ext:truth:1.5.0' (runtime) --> 'androidx.test:core:1.5.0' Dependency path 'RussianRockSongBook4:app:unspecified' --> 'androidx.test.ext:junit:1.1.5' (runtime) --> 'androidx.test:core:1.5.0' Dependency path 'RussianRockSongBook4:app:unspecified' --> 'androidx.test.espresso:espresso-core:3.5.1' (runtime) --> 'androidx.test:core:1.5.0' Dependency path 'RussianRockSongBook4:app:unspecified' --> 'com.google.dagger:hilt-android-testing:2.50' (runtime) --> 'androidx.test:core:1.4.0' Dependency path 'RussianRockSongBook4:app:unspecified' --> 'androidx.compose.ui:ui-test-junit4:1.7.0-alpha01' (releaseRuntimeElements-published) --> 'androidx.compose.ui:ui-test-junit4-android:1.7.0-alpha01' (releaseRuntimeElements-published) --> 'androidx.test:core:1.5.0'

danysantiago commented 9 months ago

I believe the version constraints you are seeing are set by the Android Studio Plugin, and usually show up when the instrumentation test or unit tests or the actual app have different versions of the same dependency. In your case its likely unit tests, can you try adding androidx.test:core:1.4.0 as a testImplementation too? Along with androidTestImplementation. Alternative you can specify your androidx.test:core and exclude androidx.test:core from hilt-android-testing via the 'exclude' APIs Gradle offer: https://docs.gradle.org/current/userguide/dependency_downgrade_and_exclude.html#sec:excluding-transitive-deps

Some more info on this can be found in: https://developer.android.com/build/dependencies#classpath_conflicts

tabatsky commented 9 months ago

Thank you very much!

Upgrade all the androidx.test dependencies to the latest alpha versions and adding the following lines to the build.gradle did the trick:

debugImplementation("androidx.test:core") {
    version {
        strictly versions.androidXTestCore
    }
}

testImplementation("androidx.test:core") {
    version {
        strictly versions.androidXTestCore
    }
}

androidTestImplementation("androidx.test:core") {
    version {
        strictly versions.androidXTestCore
    }
}

androidTestImplementation("androidx.test.ext:junit") {
    version {
        strictly versions.androidXJUnit
    }
}

androidTestImplementation(testDeps.espressoContrib) {
    exclude group: 'org.checkerframework', module: 'checker'
}

androidTestImplementation(testDeps.hiltAndroidTesting) {
    exclude group: 'androidx.test', module: 'core'
}
testImplementation(testDeps.hiltAndroidTesting) {
    exclude group: 'androidx.test', module: 'core'
}
kaptAndroidTest testDeps.hiltAndroidCompiler

androidTestImplementation testDeps.composeUiTest
androidTestImplementation(testDeps.composeUiTestJunit) {
    exclude group: 'androidx.text', module: 'core'
}