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

使用Retrofit时的单元测试:接口定义与UI测试实现问询

没问题,我来帮你完成这个Retrofit调用后的UI单元测试,咱们一步步来实现:

完成Retrofit调用后的UI单元测试方案

1. 先添加必要的测试依赖

首先确保你的build.gradle(Module级别)里包含这些测试库,用来Mock依赖、模拟网络请求:

testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:4.5.1'
testImplementation 'com.squareup.okhttp3:mockwebserver:4.10.0'
testImplementation 'com.google.code.gson:gson:2.10.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'org.mockito:mockito-android:4.5.1'

2. 完善测试类的结构与初始化

补全你的测试类成员变量,并用@Before/@After完成初始化和清理工作:

@RunWith(AndroidJUnit4.class)
public class TestTimetablePresenter {
    private static List<Departure> DEPARTURES = Lists.newArrayList(
        new Departure("L006", "Stockholm", new Datetime(1461056400, "GMT+02:00")),
        new Departure("L007", "Berlin", new Datetime(1461056500, "GMT+02:00")));

    @Mock
    private TimetableContract.View mockView; // 补全View接口的类型

    private MockWebServer mockWebServer;
    private TimetableService timetableService;
    private TimetablePresenter presenter; // 替换成你实际的Presenter类名

    @Before
    public void setUp() throws Exception {
        // 初始化Mockito
        MockitoAnnotations.openMocks(this);

        // 启动MockWebServer模拟网络请求
        mockWebServer = new MockWebServer();
        mockWebServer.start();

        // 创建指向MockServer的Retrofit实例
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(mockWebServer.url("/"))
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        // 生成测试用的TimetableService
        timetableService = retrofit.create(TimetableService.class);

        // 初始化Presenter,传入Mock的View和Service
        presenter = new TimetablePresenter(mockView, timetableService);
    }

    @After
    public void tearDown() throws Exception {
        // 测试结束后关闭MockServer
        mockWebServer.shutdown();
    }
}

3. 编写「请求成功」的UI测试用例

这个用例用来验证:当Retrofit成功返回数据时,Presenter会正确调用View的方法更新UI:

@Test
public void loadTimetable_success_updatesDepartureList() throws InterruptedException {
    // 1. 构造模拟的响应数据
    Flixbus mockFlixbus = new Flixbus();
    mockFlixbus.setDepartures(DEPARTURES); // 假设Flixbus类有该方法存储Departure列表
    String jsonResponse = new Gson().toJson(mockFlixbus);

    // 2. 让MockServer返回成功响应
    mockWebServer.enqueue(new MockResponse()
            .setBody(jsonResponse)
            .setResponseCode(200));

    // 3. 触发Presenter的加载逻辑
    presenter.loadTimetable(); // 替换成你Presenter中触发Retrofit调用的方法名

    // 4. 验证UI更新逻辑是否执行
    // 等待异步请求完成,验证View是否正确显示数据
    Mockito.verify(mockView, Mockito.timeout(1000)).showDepartures(DEPARTURES);
    // 额外验证加载状态的切换(如果你的Presenter有这个逻辑)
    Mockito.verify(mockView).showLoading();
    Mockito.verify(mockView).hideLoading();
}

4. 编写「请求失败」的UI测试用例

这个用例用来验证:当Retrofit请求失败时,Presenter会调用View显示错误信息:

@Test
public void loadTimetable_failure_showsErrorMessage() throws InterruptedException {
    // 1. 让MockServer返回错误响应
    mockWebServer.enqueue(new MockResponse()
            .setResponseCode(500)
            .setBody("Internal Server Error"));

    // 2. 触发Presenter的加载逻辑
    presenter.loadTimetable();

    // 3. 验证错误提示逻辑是否执行
    Mockito.verify(mockView, Mockito.timeout(1000)).showError(Mockito.anyString());
    Mockito.verify(mockView).showLoading();
    Mockito.verify(mockView).hideLoading();
}

关键注意事项

  • 避免真实网络依赖:用MockWebServer模拟服务器响应,让测试不依赖网络环境,速度更快且结果稳定。
  • 异步调用处理:Retrofit的Call默认是异步执行的,所以用Mockito.timeout()来等待请求完成,确保能捕获到View的方法调用。
  • 数据匹配准确性:如果需要精确匹配DEPARTURES参数,要确保Departure类重写了equals()和hashCode()方法,否则Mockito无法判断数据是否一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:02:25