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初始化

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

正常setup的方法:

import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowSubscriptionManager;

@RunWith(RobolectricTestRunner.class)
@Config(sdk = {33})
public class Test {

    @Mock
    private Context mockContext;

    @Mock
    private SubscriptionManager mockSubscriptionManager;

    @Mock
    private SubscriptionInfo mockSubscriptionInfo1;

    @Mock
    private SubscriptionInfo mockSubscriptionInfo2;

    @Before
    public void setUp() {
        MockitoAnnotations.openMocks(this);

        // 初始化使用Mock的Context
        mockContext = mock(Context.class);
        when(mockContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn(mockSubscriptionManager);
    }

}

问题2:静态对象非mock,

    //test报错代码
    @Test
    public void testGetUriForCurrSubId_validSubId() {
        Uri baseUri = Uri.parse("content://test");

        when(mockSubscriptionInfo.getSubscriptionId()).thenReturn(1);
        //TODO: when 需要传入mock 对象
        when(SubscriptionManager.isValidSubscriptionId(1)).thenReturn(true);

        Uri resultUri = mFragment.getUriForCurrSubId(baseUri);
        assertEquals(Uri.parse("content://test/subId/1"), resultUri);
    }

报错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文件中添加以下依赖项:

dependencies {
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.mockito:mockito-core:4.2.0'
    testImplementation 'org.powermock:powermock-api-mockito2:2.0.9'
    testImplementation 'org.powermock:powermock-module-junit4:2.0.9'
}

调整后的测试类:

    @Test
    public void testGetUriForCurrSubId_validSubId() {
        Uri baseUri = Uri.parse("content://test");

        when(mSubscriptionInfo.getSubscriptionId()).thenReturn(1);

        //调整方案使用PowerMockit,直接用mockStatic会说对象从来没使用
        PowerMockito.mockStatic(SubscriptionManager.class);
        PowerMockito.when(SubscriptionManager.isValidSubscriptionId(1)).thenReturn(true);

        Uri resultUri = uriGenerator.getUriForCurrSubId(baseUri

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

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

还没有评论