使用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
相关产品推荐
相关产品推荐

