在 Robolectric 中启动一个 Activity
非常简单,它通过 Robolectric.buildActivity(...)
这个核心 API 来构建和启动 Activity,支持模拟 Android 环境,无需真机或模拟器,非常适合单元测试和组件测试。
✅ 一、Robolectric 启动 Activity 的基本用法
1. 引入依赖(确保你已配置 Robolectric)
在 build.gradle
(Module) 中确保你有类似如下的依赖(以 JUnit 4 / Robolectric 4.x 为例):
groovy
testImplementation 'org.robolectric:robolectric:4.10' // 请根据最新版本调整
testImplementation 'junit:junit:4.13.2'
如果你用的是 JUnit 5,也可以使用 Robolectric 的对应支持,但本文以 JUnit 4 为例。
2. 启动一个 已知具体类 的 Activity(最常用方式)
假如你有一个 MyActivity
,你想在测试中启动它:
java
@RunWith(RobolectricTestRunner.class) // 必须加这个 Runner
public class MyActivityTest {
@Test
public void testActivityLaunch() {
// 1. 构建并启动 Activity(无 Intent)
Activity activity = Robolectric.buildActivity(MyActivity.class)
.create() // 调用 onCreate()
.start() // 调用 onStart()
.resume() // 调用 onResume()
.get(); // 获取启动后的 Activity 实例
// 2. 断言 Activity 启动成功
assertNotNull(activity);
// 你可以继续操作 UI,比如查找控件、点击按钮等
// TextView textView = activity.findViewById(R.id.my_text_view);
}
}
⭐ 说明:
Robolectric.buildActivity(YourActivity.class)
表示你要启动哪个 Activity。.create().start().resume()
是模拟 Activity 生命周期,通常你至少要调用到.resume()
,才能看到完整的 UI 状态。.get()
返回启动后的 Activity 实例,你可以对其进行各种操作和断言。
3. 启动一个 Activity 并传入自定义 Intent
如果你想模拟从某个地方(比如另一个 Activity 或 Service)通过 Intent 启动目标 Activity,并带上参数,可以这样:
java
@Test
public void testActivityLaunchWithIntent() {
// 1. 创建一个带参数的 Intent
Intent intent = new Intent(ApplicationProvider.getApplicationContext(), MyActivity.class);
intent.putExtra("key_name", "Hello Robolectric");
// 2. 使用 Robolectric 启动该 Activity,并传入 Intent
MyActivity activity = Robolectric.buildActivity(MyActivity.class, intent)
.create()
.start()
.resume()
.get();
// 3. 验证 Intent 中的参数是否正确接收
assertEquals("Hello Robolectric", activity.getIntent().getStringExtra("key_name"));
}
✅ 说明:
- 第二个参数就是你要传入的
Intent
,Robolectric 会用这个 Intent 来启动 Activity,就像正常 Android 系统一样。- 你可以用它来测试 深层链接、推送跳转、广告落地页跳转 等场景。
✅ 二、完整示例:启动一个 Activity 并测试其 UI
假设我们有这样一个简单的 Activity:
java
// MyActivity.java
public class MyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
TextView textView = findViewById(R.id.text_view);
textView.setText("Hello, Robolectric!");
}
}
对应的测试类可以是:
java
@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {
@Test
public void testTextViewContent() {
// 启动 Activity
MyActivity activity = Robolectric.buildActivity(MyActivity.class)
.create()
.start()
.resume()
.get();
// 找到 TextView 控件
TextView textView = activity.findViewById(R.id.text_view);
// 验证文本内容
assertEquals("Hello, Robolectric!", textView.getText().toString());
}
}
✅ 这是最常见的 UI 测试之一:启动 Activity,查找控件,验证内容。
✅ 三、如果想启动一个 动态类(通过类名字符串) 的 Activity(高级用法)
有时候你可能 不知道具体类名,但想通过反射或运行时得到的类名来启动 Activity(比如测试广告落地页被正确调起)。这时候你需要:
- 通过
Class.forName("com.example.MyActivity")
加载类; - 然后传给
Robolectric.buildActivity(Class<?>, Intent)
;
示例:
java
@Test
public void testLaunchActivityByClassName() {
try {
// 1. 动态加载 Activity 类(请替换成你实际的类名)
Class<?> activityClass = Class.forName("com.example.MyActivity");
// 2. 强制转换为 Class<? extends Activity>(需确保它是 Activity 子类)
@SuppressWarnings("unchecked")
Class<? extends Activity> castedClass = (Class<? extends Activity>) activityClass;
// 3. 启动该 Activity
Activity activity = Robolectric.buildActivity(castedClass)
.create()
.start()
.resume()
.get();
assertNotNull(activity);
} catch (ClassNotFoundException e) {
fail("无法加载 Activity 类: com.example.MyActivity");
}
}
🧠 注意:这种方式适合在动态测试、反射调用、自动化测试等高级场景中使用。一般建议直接用
Robolectric.buildActivity(YourActivity.class)
更安全直观。
✅ 四、关于生命周期方法(.create()
, .start()
, .resume()
...)
Robolectric 允许你控制 Activity 的生命周期模拟,常见方法有:
方法 | 对应生命周期 | 是否必须 | 说明 |
---|---|---|---|
.create() |
onCreate() | 推荐 | 创建 Activity,加载布局 |
.start() |
onStart() | 可选 | 开始可见状态 |
.resume() |
onResume() | 推荐 | 可交互状态,UI 通常在此时完成 |
.pause() |
onPause() | 可选 | 暂停状态 |
.stop() |
onStop() | 可选 | 停止状态 |
.destroy() |
onDestroy() | 可选 | 销毁状态 |
✅ 一般测试中,你至少要调用到
.resume()
,才能保证 UI 被正确初始化,比如setContentView()
生效、控件可被找到。
✅ 五、总结:Robolectric 启动 Activity 的几种常见方式
场景 | 方法 | 示例 |
---|---|---|
启动一个已知 Activity 类 | Robolectric.buildActivity(MyActivity.class) |
最常用,直接传类 |
带 Intent 启动 Activity | Robolectric.buildActivity(MyActivity.class, intent) |
模拟跳转、传参 |
模拟完整生命周期 | .create().start().resume().get() |
保证 UI 初始化完成 |
仅初始化不启动 | 只调用.create() |
比如只测试 onCreate() |
通过类名字符串启动(反射) | Class.forName("xxx"). → 转成 Class<?> 再传入 |
高级用法,需异常处理 |
✅ 六、推荐写法(标准模板)
java
@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {
@Test
public void testActivityStartsCorrectly() {
// 1. 构建并启动 Activity(带或不带 Intent)
MyActivity activity = Robolectric.buildActivity(MyActivity.class)
.create() // onCreate()
.start() // onStart()
.resume() // onResume() => UI ready
.get(); // 获取 Activity 实例
// 2. 进行断言或 UI 操作
assertNotNull(activity);
// 如:TextView tv = activity.findViewById(R.id.xxx);
// assertEquals("Hi", tv.getText().toString());
}
}
📌 补充:别忘了加注解!
在测试类顶部 必须添加:
java
@RunWith(RobolectricTestRunner.class)
这是 Robolectric 测试的入口,没有它,测试无法运行在 Robolectric 模拟的 Android 环境中。
✅ 总结一句话:
使用 Robolectric 启动一个 Activity,就是调用:
Robolectric.buildActivity(YourActivity.class).create().start().resume().get();
你可以根据需求选择是否传入 Intent,是否调用完整的生命周期方法,以及是否要操作 UI 组件进行断言。