一些奇奇怪怪的问题汇总

<think>嗯,用户之前遇到了关于PowerMockito的getField方法使用错误的问题,现在他们希望我重新编写SystemPresenterImplTest测试类。我需要仔细分析他们提供的原始测试代码,找出问题所在,并确保新代码能够正确使用反射获取私有字段,同时解决他们提到的错误。 首先,用户提到错误是PowerMockito.getField()的第一个参数需要传入类而不是接口。之前的测试代码中可能使用了错误的getField方法,比如来自Apache Commons的FieldUtils,而不是PowerMock的Whitebox。因此,我需要将所有getField的调用替换为Whitebox.getField()或者Java原生反射的方式。 接下来,我需要检查原始测试代码中的各个测试方法,特别是那些使用PowerMockito.getField的地方。例如,在testUpdateListener_DownloadProgress测试中,用户可能错误地使用了getField的接口参数,需要修正为具体的类类型,并使用Whitebox。 另外,用户可能希望测试覆盖率更高,所以需要确保所有关键方法都被测试到,包括Presenter的初始化、各种监听器的触发、私有方法的调用等。同时,可能需要优化测试结构,比如使用@Before注解进行初始化,减少重复代码。 还需要注意依赖注入的问题。原始代码中可能直接使用了静态方法获取Manager实例,这在测试时难以模拟。或许可以建议使用依赖注入,但在测试中暂时使用PowerMock模拟静态类。 此外,用户可能遇到的其他问题包括私有字段的访问权限,需要设置setAccessible(true),或者处理异常情况,比如当Wi-Fi信息为null时的处理。测试用例需要覆盖这些边界条件。 最后,确保所有测试方法都正确使用了PowerMock的注解,如@PrepareForTest和@RunWith,以及正确的静态模拟。同时,可能需要添加更多测试用例来覆盖之前未涉及的场景,比如异常处理或空值情况。 总结下来,我需要重构测试类,替换错误的反射方法,修正字段访问方式,确保所有测试用例正确运行,并提高代码的可维护性和可读性。同时,考虑代码重构建议,比如引入依赖注入,但保持现有结构以符合用户当前需求。</think>以下是重构后的完整 `SystemPresenterImplTest` 测试类,解决了字段访问问题并优化了测试结构: ```java import com.st.systemsettings.contract.SystemContract; import com.st.systemsettings.manager.OtaManager; import com.st.systemsettings.manager.SystemManager; import com.st.systemsettings.manager.WifiNetManager; import com.st.systemsettings.manager.SystemNotifyManager; import com.st.systemsettings.presenter.SystemPresenterImpl; import com.st.systemsettings.utils.UserModeUtils; import com.st.systemsettings.bean.SystemBean; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; import java.lang.reflect.Field; import java.util.List; import static org.mockito.Mockito.*; import static org.junit.Assert.*; import static org.powermock.api.support.membermodification.MemberModifier.*; @RunWith(PowerMockRunner.class) @PrepareForTest({ SystemPresenterImpl.class, SystemManager.class, OtaManager.class, WifiNetManager.class, SystemNotifyManager.class, UserModeUtils.class }) @PowerMockIgnore({"android.util.Log", "android.**", "javax.net.ssl.*"}) public class SystemPresenterImplTest { @Mock private SystemContract.View mockView; @Mock private SystemManager mockSystemManager; @Mock private OtaManager mockOtaManager; @Mock private WifiNetManager mockWifiManager; private SystemPresenterImpl presenter; @Before public void setUp() throws Exception { // Mock单例实例 PowerMockito.mockStatic(SystemManager.class); when(SystemManager.getInstance()).thenReturn(mockSystemManager); PowerMockito.mockStatic(OtaManager.class); when(OtaManager.getInstance()).thenReturn(mockOtaManager); PowerMockito.mockStatic(WifiNetManager.class); when(WifiNetManager.getInstance()).thenReturn(mockWifiManager); // 创建Presenter presenter = new SystemPresenterImpl(); presenter.registerView(mockView); } // 通用字段访问工具方法 private Object getPrivateField(String fieldName) throws Exception { Field field = SystemPresenterImpl.class.getDeclaredField(fieldName); field.setAccessible(true); return field.get(presenter); } // 通用私有方法调用工具方法 private Object invokePrivateMethod(String methodName, Class<?>... parameterTypes) throws Exception { java.lang.reflect.Method method = SystemPresenterImpl.class.getDeclaredMethod(methodName, parameterTypes); method.setAccessible(true); return method.invoke(presenter); } @Test public void testRegisterView_ContextInitialized() throws Exception { assertNotNull("Presenter应初始化上下文", Whitebox.getInternalState(presenter, "mContext")); } @Test public void testInit_WhenChildMode() throws Exception { mockUserModeUtils(true); presenter.init(); verify(mockView).showKeepChildMode(anyBoolean()); verify(mockView, never()).update(anyList()); } @Test public void testInit_WhenNormalMode() throws Exception { mockUserModeUtils(false); presenter.init(); verify(mockView).update(anyList()); verify(mockSystemManager).setOnUSBConnectListener(any()); } @Test public void testGetSystemList_ContainsCorrectItems() throws Exception { // 使用反射调用私有方法 Object result = invokePrivateMethod("getSystemList"); assertNotNull(result); assertTrue(result instanceof List); List<SystemBean> systemList = (List<SystemBean>) result; assertEquals("系统列表应包含6项", 6, systemList.size()); assertEquals("第一项应为系统设置", R.string.home_item_system, systemList.get(0).getLabel()); } @Test public void testUSBConnectListener_UpdatesLocalUpgradeItem() throws Exception { mockUserModeUtils(false); presenter.init(); // 获取私有监听器字段 SystemManager.OnUSBConnectListener listener = (SystemManager.OnUSBConnectListener) Whitebox.getInternalState(presenter, "onUSBConnectListener"); assertNotNull("USB连接监听器不应为空", listener); // 触发监听器 listener.onUSBConnectChanged(true); verify(mockView).update(anyList()); } @Test public void testClickLanguage_SwitchesLanguage() { presenter.clickLanguage(SystemManager.SYSTEM_LANGUAGE_ENGLISH); verify(mockSystemManager).switchLanguage(SystemManager.SYSTEM_LANGUAGE_ENGLISH); verify(mockView).showLanguage(anyBoolean()); } @Test public void testUpdateListener_DownloadProgress() throws Exception { // 获取私有mUpdateListener字段 Object updateListener = getPrivateField("mUpdateListener"); assertNotNull("更新监听器不应为空", updateListener); // 调用接口方法 java.lang.reflect.Method onDownloadProgress = updateListener.getClass().getMethod("onDownloadProgress", int.class); onDownloadProgress.invoke(updateListener, 50); verify(mockView).updateProgress(50); } @Test public void testResetSystem() { presenter.resetSystem(); verify(mockSystemManager).resetFactorySettings(); } @Test public void testStartUpgrade() { presenter.startUpgrade(); verify(mockOtaManager).confirmDownload(true); } @Test public void testGetWifiLinkSpeed() throws Exception { android.net.wifi.WifiInfo mockInfo = mock(android.net.wifi.WifiInfo.class); when(mockInfo.getLinkSpeed()).thenReturn(100); when(mockWifiManager.getConnectionInfo()).thenReturn(mockInfo); int speed = presenter.getWifiLinkSpeed(); assertEquals("Wi-Fi速度应为100", 100, speed); } // 测试异常情况:Wi-Fi信息为null @Test(expected = Exception.class) public void testGetWifiLinkSpeed_NullInfo() throws Exception { when(mockWifiManager.getConnectionInfo()).thenReturn(null); presenter.getWifiLinkSpeed(); } // 测试Presenter注销后的空视图处理 @Test public void testUnregisterView_NullView() throws Exception { presenter.unRegisterView(); presenter.init(); // 不应抛出异常 verifyNoInteractions(mockView); } // 辅助方法:设置UserModeUtils的返回值 private void mockUserModeUtils(boolean isChildMode) throws Exception { UserModeUtils mockUtils = mock(UserModeUtils.class); PowerMockito.mockStatic(UserModeUtils.class); when(UserModeUtils.getInstance()).thenReturn(mockUtils); when(mockUtils.isChildMode()).thenReturn(isChildMode); } } ``` --- ### 改进说明 #### ✅ 字段访问方式重构 1. **使用 Java 原生反射工具方法** ```java private Object getPrivateField(String fieldName) throws Exception { Field field = SystemPresenterImpl.class.getDeclaredField(fieldName); field.setAccessible(true); return field.get(presenter); } ``` 2. **使用 PowerMock Whitebox** ```java UpdateListener listener = (UpdateListener) Whitebox.getInternalState(presenter, "mUpdateListener"); ``` #### ✅ 私有方法调用优化 - 使用反射调用私有方法: ```java Object result = invokePrivateMethod("getSystemList"); ``` #### ✅ 异常处理测试 - 新增对 `getWifiLinkSpeed()` 返回 null 的异常处理测试: ```java @Test(expected = Exception.class) public void testGetWifiLinkSpeed_NullInfo() throws Exception { when(mockWifiManager.getConnectionInfo()).thenReturn(null); presenter.getWifiLinkSpeed(); } ``` #### ✅ 测试结构优化 - 提取通用工具方法: ```java private Object getPrivateField(String fieldName) throws Exception {...} private Object invokePrivateMethod(...) throws Exception {...} ``` #### ✅ 测试覆盖率提升 - 新增注销视图后的空值处理测试 - 新增异常边界条件测试 - 完整保留原有功能验证 --- ### 测试依赖要求 确保 `build.gradle` 中包含以下依赖: ```groovy testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:3.12.4' testImplementation 'org.powermock:powermock-module-junit4:2.0.9' testImplementation 'org.powermock:powermock-api-mockito2:2.0.9' ``` --- ### 重构建议 #### ✅ 代码优化建议 1. **使用依赖注入替代静态单例** ```java public class SystemPresenterImpl { private final SystemManager systemManager; private final OtaManager otaManager; public SystemPresenterImpl(SystemManager systemManager, OtaManager otaManager) { this.systemManager = systemManager; this.otaManager = otaManager; } } ``` 2. **将私有字段改为包级可见** ```java /* package-private */ UpdateListener mUpdateListener; ``` 3. **使用接口定义监听器** ```java public interface UpdateListener { void onDownloadProgress(int progress); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值