美文网首页
Android单元测试框架Robolectric3.0的使用

Android单元测试框架Robolectric3.0的使用

作者: poweru | 来源:发表于2017-12-07 15:33 被阅读0次

    单元测试是什么

    单元测试 是针对 程序的最小单元 来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。一个单元可能是单个程序、类、对象、方法等。

    单元测试意义

    • 减少bug
    • 快速定位bug
    • 提高代码质量
    • 减少调试时间

    Robolectric3.0环境搭建

    在build.gradle中配置如下依赖关系:

    testCompile "org.robolectric:robolectric:3.0"
    

    通过注解配置TestRunner

    @RunWith(RobolectricTestRunner.class)
    @Config(constants = BuildConfig.class)
    public class SampleActivityTest {
    
    }
    

    说明:上面配置的是RobolectricTestRunner,而不是RobolectricGradleTestRunner,在Robolectric之前的版本是有这个RobolectricGradleTestRunner,但在最新的版本上却没有了,也不知道是为什么。但是有一点,使用最新版本后,倒是没有出现找不到资源文件res的警告。最新的Robolectric最高可支持Android API 23。

    Android Studio的配置

    working directory 设置为$MODULE_DIR$
    如果在测试过程遇见如下问题,解决的方式就是设置working directory的值:

    java.io.FileNotFoundException: build\intermediates\bundles\debug\AndroidManifest.xml (系统找不到指定的路径。)
    

    设置方法如下图所示:

    Edit Configurations Working directory的配置

    编写Activity测试用例代码

    public class ComplaintActivityTest extends BaseRobolectricTestCase {
    
    @Test
    @PrepareForTest({AppUtil.class, OAuthManager.class, NetUtil.class})
    public void jumpCompensate() throws Exception {
        PowerMockito.mockStatic(AppUtil.class);
        PowerMockito.when(AppUtil.getVersionName()).thenReturn("1.4.0");
    
        PowerMockito.mockStatic(OAuthManager.class);
        OAuthManager mockOAuth = PowerMockito.mock(OAuthManager.class);
        PowerMockito.when(OAuthManager.getInstance()).thenReturn(mockOAuth);
        PowerMockito.when(mockOAuth.getSargerasToken()).thenReturn("c97faa92-34ea-4248-a19e-9a9fb848b29b");
    
        AppApplication.mInstance = getApplication();
    
        PowerMockito.mockStatic(NetUtil.class);
        PowerMockito.when(NetUtil.isNetworkConnected(AppApplication.getInstance())).thenReturn(true);
    
        PreferenceUtil.init();
        PersistentPreferenceUtil.init();
    
        ComplaintActivity complaintActivity = Robolectric.buildActivity(ComplaintActivity.class).create().get();
        assertNotNull(complaintActivity);
        complaintActivity.jumpCompensate();
        Intent expectedIntent = new Intent(complaintActivity, HelpActivity.class);
        ShadowActivity shadowActivity = Shadows.shadowOf(complaintActivity);
        Intent actualIntent = shadowActivity.getNextStartedActivity();
        Assert.assertEquals(expectedIntent.getComponent().getClassName(), actualIntent.getComponent().getClassName());
    }
    

    }

    上面前一部分代码主要设置ComplaintActivity运行所依赖的属性,这也是在单元测试最为繁琐的地方,因为不是运行在真实的Android环境中。具体分析如下:

    1. 通过注解@PrepareForTest({AppUtil.class, OAuthManager.class, NetUtil.class})定义PowerMockito要mock的类;

    2. 在Robolectric中读取不到apk的版本号,通过PowerMockito.when(AppUtil.getVersionName()).thenReturn("1.4.0")mock指定AppUtil.getVersionName()的返回值"1.4.0",即版本号;

    3. 通过AppApplication.mInstance = getApplication();使用Robolectric运行环境中的application对AppApplication.mInstance进行依赖注入,因为在很多类中都会用到AppApplication.mInstance进行初始化,例如SharedPreference、SQlite、单例类等;

    4. ComplaintActivity complaintActivity = Robolectric.buildActivity(ComplaintActivity.class).create().get();使用Robolectric创建ComplaintActivity对象,其中create()方法就是对应于调用Activity生命周期的onCreate()方法,此外Robolectric支持链式调用如:Robolectric.buildActivity(ComplaintActivity.class).create().resume().get();

    5. assertNotNull(complaintActivity);验证complaintActivity是否跑起来;

    6. 最后一部分代码就是调用jumpCompensate方法进行跳转,验证跳转的Intent是否符合预期;

    至于其他的一些如Fragment、Dialog、Toast等验证,可以参考这篇博客,这里就不展开。至于其他的一些如Fragment、Dialog、Toast等验证,可以参考这篇博客,这里就不展开。

    Robolectric常见的坑

    1. Application空指针问题

    这是因为SharedPreferences和单例等类初始化时需要依赖Application对象,我们常见的用法是使用Application.getApplication()方法来获取,在Robolectric中则是需要使用RuntimeEnvironment.application来进行替换,上面就是通过依赖的方式进行替换。

    2. AppCompatActivity错误

    假如你在Robolectric的@Config注解中配置了manifest = Config.NONE,那就完蛋了,因为在网上根本找不解决的方法,你遇到如下异常不能使用support V7包的类:

    java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
    
     at android.support.v7.app.AppCompatDelegateImplV7.createSubDecor(AppCompatDelegateImplV7.java:343)
     at android.support.v7.app.AppCompatDelegateImplV7.ensureSubDecor(AppCompatDelegateImplV7.java:312)
     at android.support.v7.app.AppCompatDelegateImplV7.initWindowDecorActionBar(AppCompatDelegateImplV7.java:172)
     at android.support.v7.app.AppCompatDelegateImplBase.getSupportActionBar(AppCompatDelegateImplBase.java:88)
     at android.support.v7.app.AppCompatActivity.getSupportActionBar(AppCompatActivity.java:110)
     at me.ele.shopcenter.components.BaseActivity.initActionBar(BaseActivity.java:104)
     at me.ele.shopcenter.components.BaseActivity.onCreate(BaseActivity.java:52)
     at me.ele.shopcenter.ui.order.ComplaintActivity.onCreate(ComplaintActivity.java:93)
     at android.app.Activity.performCreate(Activity.java:6251)
     at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:231)
    

    解决的方式就是去掉manifest = Config.NONE配置,这是坑爹的,我就遇到这个错误,花了好长一段时间才发现是这个配置导致的。

    3. 找不到android.net.http.AndroidHttpClient的类文件

    在Android API23开始,google就移除了HttpClient相关的类,有两种方法解决上述问题。
    在build.gradle添加应用useLibrary ‘org.apache.http.legacy’

    相关文章

      网友评论

          本文标题:Android单元测试框架Robolectric3.0的使用

          本文链接:https://www.haomeiwen.com/subject/apncixtx.html