0


Android 应用单元测试涉及 Telephony 环境初始化问题

Telephony 相关类注入问题

常见问题是对象null,或者调用静态对象的时候怎么将静态类设置成mock对象传入when()?

常见问题和解决方案简介
问题解决方案when(非mock.method)
在被测试类中,创建一个辅助类来处理静态方法调用。

在测试类中,调用辅助类的接口。
对象nullwhen.thenReturn 或者 doReturn.when 预置方法体执行需要的mock对象值。

SubscriptionManager

问题1:对象null

Cannot invoke "android.telephony.SubscriptionManager.getActiveSubscriptionInfoList()" because "this.mSubscriptionManager" is null
java.lang.NullPointerException: Cannot invoke "android.telephony.SubscriptionManager.getActiveSubscriptionInfoList()" because "this.mSubscriptionManager" is null
at com.demo.settings.util.SimHotSwapHandler.<init>(SimHotSwapHandler.java:32)

错误初始化方法,因为when不能传入非mock对象,是因为context没有mock初始化

  1. @Before
  2. public void setUp() {
  3. // 将mock的SubscriptionManager与测试环境中Context的系统服务绑定
  4. when(mockContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn(mockSubscriptionManager);
  5. }

正常setup的方法:

  1. import org.robolectric.RobolectricTestRunner;
  2. import org.robolectric.RuntimeEnvironment;
  3. import org.robolectric.annotation.Config;
  4. import org.robolectric.shadows.ShadowApplication;
  5. import org.robolectric.shadows.ShadowSubscriptionManager;
  6. @RunWith(RobolectricTestRunner.class)
  7. @Config(sdk = {33})
  8. public class Test {
  9. @Mock
  10. private Context mockContext;
  11. @Mock
  12. private SubscriptionManager mockSubscriptionManager;
  13. @Mock
  14. private SubscriptionInfo mockSubscriptionInfo1;
  15. @Mock
  16. private SubscriptionInfo mockSubscriptionInfo2;
  17. @Before
  18. public void setUp() {
  19. MockitoAnnotations.openMocks(this);
  20. // 初始化使用Mock的Context
  21. mockContext = mock(Context.class);
  22. when(mockContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn(mockSubscriptionManager);
  23. }
  24. }

问题2:静态对象非mock,

  1. //test报错代码
  2. @Test
  3. public void testGetUriForCurrSubId_validSubId() {
  4. Uri baseUri = Uri.parse("content://test");
  5. when(mockSubscriptionInfo.getSubscriptionId()).thenReturn(1);
  6. //TODO: when 需要传入mock 对象
  7. when(SubscriptionManager.isValidSubscriptionId(1)).thenReturn(true);
  8. Uri resultUri = mFragment.getUriForCurrSubId(baseUri);
  9. assertEquals(Uri.parse("content://test/subId/1"), resultUri);
  10. }

报错console:

org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.

For example:
when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:

  1. you stub either of: final/private/equals()/hashCode() methods.
    Those methods cannot be stubbed/verified.
    Mocking methods declared on non-public parent classes is not supported.

  2. inside when() you don't call method on mock but on some other object.

    at com.demo.settings.DemoSettingsTest.testGetUriForCurrSubId_invalidSubId(DemoSettingsTest.java:305)
    at java.base@17.0.7/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base@17.0.7/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base@17.0.7/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

分析:

在上述代码中,导致when()方法抛出错误的原因可能是尝试模拟静态方法。静态方法不能被直接模拟。

方案1、使用PowerMockito来模拟静态方法

通过使用PowerMockito,它提供了额外的功能来模拟静态方法。首先,包括适当的依赖项:在build.gradle文件中添加以下依赖项:

  1. dependencies {
  2. testImplementation 'junit:junit:4.13.2'
  3. testImplementation 'org.mockito:mockito-core:4.2.0'
  4. testImplementation 'org.powermock:powermock-api-mockito2:2.0.9'
  5. testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
  6. }

调整后的测试类:

  1. @Test
  2. public void testGetUriForCurrSubId_validSubId() {
  3. Uri baseUri = Uri.parse("content://test");
  4. when(mSubscriptionInfo.getSubscriptionId()).thenReturn(1);
  5. //调整方案使用PowerMockit,直接用mockStatic会说对象从来没使用
  6. PowerMockito.mockStatic(SubscriptionManager.class);
  7. PowerMockito.when(SubscriptionManager.isValidSubscriptionId(1)).thenReturn(true);
  8. Uri resultUri = uriGenerator.getUriForCurrSubId(baseUri

本文转载自: https://blog.csdn.net/qq_38666896/article/details/144206016
版权归原作者 Dic- 所有, 如有侵权,请联系我们删除。

“Android 应用单元测试涉及 Telephony 环境初始化问题”的评论:

还没有评论