GitHub Actions中Android Instrumentation测试因FCMService崩溃求助
问题分析
本地测试正常但CI流程中测试崩溃,核心原因是GitHub Actions环境中,FCMService在测试进程启动阶段被系统/Firebase初始化触发,而此时Hilt的测试组件还未通过HiltAndroidRule.init()完成初始化,导致Service尝试注入依赖时触发组件未创建的异常。
以下是针对性解决方案:
解决方案1:在测试Manifest中禁用/替换FCMService
通过测试环境的Manifest覆盖原Service配置,阻止系统启动需要Hilt注入的FCMService:
- 创建
src/androidTest/AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.xxx.xxx"> <application> <!-- 禁用原FCMService,避免测试进程启动时触发 --> <service android:name="org.xxx.xxx.FCMService" android:enabled="false" android:exported="false" /> </application> </manifest>
或者用空实现的测试Service替换原FCMService,拦截FCM相关的Intent:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.xxx.xxx"> <application> <service android:name="org.xxx.xxx.TestFCMService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> </application> </manifest>
对应的TestFCMService实现:
class TestFCMService : FirebaseMessagingService() { override fun onMessageReceived(message: RemoteMessage) {} override fun onNewToken(token: String) {} }
解决方案2:调整测试Runner与Hilt的配合
将测试类的Runner替换为HiltTestRunner(而非MockitoJUnitRunner),同时保留Mockito功能:
- 修改测试类代码:
@RunWith(HiltTestRunner::class) @HiltAndroidTest class ExampleInstrumentedTest { @get:Rule val hiltRule = HiltAndroidRule(this) @Mock lateinit var preferenceService: PreferenceService @Before fun init() { hiltRule.inject() MockitoAnnotations.openMocks(this) } @Test fun useAppContext() { println("Print message <- useAppContext <- ExampleInstrumentationTest") } }
- 确保build.gradle中添加必要依赖:
androidTestImplementation "com.google.dagger:hilt-android-testing:2.44" androidTestImplementation "org.mockito:mockito-android:4.8.1" androidTestImplementation "androidx.test.ext:junit-ktx:1.1.5" kaptAndroidTest "com.google.dagger:hilt-android-compiler:2.44"
解决方案3:为FCMService提供测试用依赖
创建测试专属Hilt模块,将FCMService所需的依赖替换为Mock实例,配合前两种方案使用:
@Module @TestInstallIn(components = [ServiceComponent::class], replaces = [YourOriginalPreferenceModule::class]) object TestPreferenceModule { @Provides fun providePreferenceService(): PreferenceService { return Mockito.mock(PreferenceService::class.java) } }
内容的提问来源于stack exchange,提问作者Dinesh Sarma
相关产品推荐
相关产品推荐

