You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Espresso对带用户授权的Sms Retriever进行UI测试?

测试SmsRetriever广播接收与OTP自动填充逻辑(Espresso + Mockito)

没问题,我来帮你梳理如何用Espresso和Mockito完成这个测试——核心是模拟SmsRetriever.SMS_RETRIEVED_ACTION广播的触发流程,验证你的onActivityResult代码能否正确提取OTP并填充到EditText中。下面是分步实现方案:


1. 确认测试依赖

首先确保你的Module级build.gradle里已经添加了必要的测试库:

androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'org.mockito:mockito-android:5.6.0'
androidTestImplementation 'androidx.test:rules:1.5.0'

2. 初始化测试环境

创建Instrumented测试类,用ActivityTestRule启动承载OTP Fragment的宿主Activity,同时准备好要测试的BroadcastReceiver实例:

@RunWith(AndroidJUnit4::class)
class OtpFragmentTest {

    @get:Rule
    val activityRule = ActivityTestRule<YourHostActivity>(YourHostActivity::class.java)

    private lateinit var testBroadcastReceiver: BroadcastReceiver

    @Before
    fun setup() {
        // 获取Fragment实例,拿到你注册的BroadcastReceiver
        val otpFragment = activityRule.activity.supportFragmentManager
            .findFragmentById(R.id.your_fragment_container) as MyOtpFragment
        testBroadcastReceiver = otpFragment.yourBroadcastReceiver // 假设Fragment持有Receiver的引用
    }
}

3. 模拟广播触发,验证Consent Intent的启动

我们先构造一个成功状态的广播Intent,手动调用Receiver的onReceive方法,验证它是否正确触发了startActivityForResult:

@Test
fun testBroadcastReceiverTriggersConsentFlow() {
    // 1. 构造成功的Status对象
    val successStatus = Status(CommonStatusCodes.SUCCESS, "OTP检索成功")

    // 2. 构造包含Consent Intent的广播Intent
    val consentIntent = Intent(SmsRetriever.ACTION_SMS_USER_CONSENT)
    val broadcastIntent = Intent(SmsRetriever.SMS_RETRIEVED_ACTION).apply {
        putExtra(SmsRetriever.EXTRA_STATUS, successStatus)
        putExtra(SmsRetriever.EXTRA_CONSENT_INTENT, consentIntent)
    }

    // 3. 调用Receiver的onReceive方法
    testBroadcastReceiver.onReceive(activityRule.activity, broadcastIntent)

    // 可选:如果想验证startActivityForResult被调用,可结合Mockito做验证
    // 注意:如果用的是registerForActivityResult,需要mock ActivityResultLauncher并验证
}

4. 模拟onActivityResult返回,验证OTP填充

直接模拟onActivityResult的调用,然后用Espresso检查EditText的内容是否正确:

@Test
fun testOnActivityResultFillsOtpCorrectly() {
    val testOtp = "123456"
    val otpFragment = activityRule.activity.supportFragmentManager
        .findFragmentById(R.id.your_fragment_container) as MyOtpFragment

    // 构造模拟的返回Intent,携带测试用的OTP
    val resultIntent = Intent().apply {
        putExtra(SmsRetriever.EXTRA_SMS_MESSAGE, testOtp)
    }

    // 手动调用Fragment的onActivityResult方法
    otpFragment.onActivityResult(SMS_REQUEST_CODE, Activity.RESULT_OK, resultIntent)

    // 用Espresso验证EditText是否被正确填充
    onView(withId(R.id.et_otp))
        .check(matches(withText(testOtp)))
}

5. 完整流程模拟(广播→同意→填充)

如果你想测试从广播触发到OTP填充的完整流程,可以用Espresso的intending拦截Consent Intent,直接返回成功结果:

@Test
fun testFullOtpRetrievalFlow() {
    val testOtp = "654321"
    val otpFragment = activityRule.activity.supportFragmentManager
        .findFragmentById(R.id.your_fragment_container) as MyOtpFragment

    // 拦截Consent Intent,直接返回携带OTP的成功结果
    intending(hasAction(SmsRetriever.ACTION_SMS_USER_CONSENT))
        .respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, Intent().apply {
            putExtra(SmsRetriever.EXTRA_SMS_MESSAGE, testOtp)
        }))

    // 触发广播Receiver
    val successStatus = Status(CommonStatusCodes.SUCCESS, "Success")
    val consentIntent = Intent(SmsRetriever.ACTION_SMS_USER_CONSENT)
    val broadcastIntent = Intent(SmsRetriever.SMS_RETRIEVED_ACTION).apply {
        putExtra(SmsRetriever.EXTRA_STATUS, successStatus)
        putExtra(SmsRetriever.EXTRA_CONSENT_INTENT, consentIntent)
    }
    testBroadcastReceiver.onReceive(activityRule.activity, broadcastIntent)

    // 等待流程完成,验证OTP填充
    onView(withId(R.id.et_otp))
        .check(matches(withText(testOtp)))
}

小提示

  • 如果你的BroadcastReceiver是动态注册的,要确保测试前已经完成注册,或者在测试的setup方法中手动注册。
  • 如果你用的是registerForActivityResult而非传统的startActivityForResult,需要用Mockito mockActivityResultLauncher,并验证它的launch方法是否被正确调用。
  • 确保测试中使用的SMS_REQUEST_CODE和你业务代码中的常量完全一致。

内容的提问来源于stack exchange,提问作者Jokubas Trinkunas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 17:07:38