美文网首页Android开发Android开发经验谈Android开发
扣丁学堂Android开发培训解析如何对Android原生应用进

扣丁学堂Android开发培训解析如何对Android原生应用进

作者: 994d14631d16 | 来源:发表于2018-08-15 10:29 被阅读7次

  今天扣丁学堂Android培训老师给大家介绍一下关于关于在Android原生应用开发中,存在两种单元测试:本地JVM测试和Instrumentation测试,那么下面我们来看一下关于如何对Android原生应用进行单元测试及示例代码。

  1、本地jvm的单元测试:这种方式运行速度快,对运行环境没有特殊要求,可以很方便的做自动化测试,是单元测试首选的方法

  2、Instrumentation测试:nstrumentation测试需要运行在Android环境下,可以是模拟器或者手机等真实设备。这种方式运行速度慢,且严重依赖Android运行环境,更适合用来做集成测试

  3、准备一个简单的APP,模拟一个耗时的网络请求获得一段数据并显示在界面上,针对这个APP编写单元测试用例并进行本地单元测试。

  依赖库

  配置build.gradle

  增加编译选项,在测试中包含资源文件

  testOptions{

  unitTests{

  includeAndroidResourcestrue

  }

  }

  添加测试依赖库

  testImplementation'junit:junit:4.12'

  testImplementation'org.robolectric:robolectric:3.8'

  testImplementation'org.robolectric:shadows-supportv4:3.8'

  testImplementation'org.powermock:powermock-module-junit4:1.6.6'

  testImplementation'org.powermock:powermock-module-junit4-rule:1.6.6'

  testImplementation'org.powermock:powermock-api-mockito:1.6.6'

  testImplementation'org.powermock:powermock-classloading-xstream:1.6.6'

  testImplementation'org.mockito:mockito-all:1.10.19'

  测试Activity

  测试Activity主要是测试它各个生命周期的状态变化、对外界输入的响应是否符合预期,Activity测试完全依赖AndroidSDK,需要用Robolectric。

  Robolectric是一个开源的单元测试框架,能够完全模拟AndroidSDK并在JVM中运行。

  UI依赖于Persenter,在Activity中通过静态工厂方法创建依赖的Presenter实例,需要使用PowerMock来模拟创建Presenter过程,完成Presenter模拟对象的注入

  配置

  通过@RunWith指定使用RobolectricTestRunner

  通过@Config配置Robolectric的运行环境

  通过@PrepareForTest配置PowerMock需要模拟的静态类型

  @RunWith(RobolectricTestRunner.class)

  @Config(sdk=21,constants=BuildConfig.class)

  @PowerMockIgnore({"org.mockito.*","org.robolectric.*","android.*"})

  @PrepareForTest({PresenterFactory.class})

  @Before

  publicvoidsetUp(){

  appContext=RuntimeEnvironment.application.getApplicationContext();

  PowerMockito.mockStatic(PresenterFactory.class);

  }

  onCreate用例

  通过Robolectric的ActivityController来构建并管理activity的生命周期,运行至onCreate阶段,然后验证这个阶段text1是否正确初始化

  @Test

  publicvoidonCreate_text1(){

  MainActivityactivity=Robolectric.buildActivity(MainActivity.class).create().get();

  Stringexpect=appContext.getString(R.string.hell_world);

  assertEquals(expect,((TextView)activity.findViewById(R.id.lbl_text1)).getText());

  }

  ClickButton1用例

  Activity完全显示以后,验证button1的click操作是否显示toast消息

  @Test

  publicvoidbtn1_click(){

  MainActivityactivity=Robolectric.setupActivity(MainActivity.class);

  activity.findViewById(R.id.btn_1).performClick();

  Stringexpect=appContext.getString(R.string.hell_world);

  assertEquals(expect,ShadowToast.getTextOfLatestToast());

  }

  ClickButton2用例

  Activity完全显示以后,验证button2的click操作是否调用了presenter的fetch方法

  @Test

  publicvoidbtn2_click(){

  MainContract.Presenterpresenter=Mockito.mock(MainContract.Presenter.class);

  PowerMockito.when(PresenterFactory.create(Mockito.any(MainContract.View.class),Mockito.any(AppExecutors.class)))

  .thenReturn(presenter);

  MainActivityactivity=Robolectric.setupActivity(MainActivity.class);

  activity.findViewById(R.id.btn_2).performClick();

  Mockito.verify(presenter,Mockito.times(1))

  .fetch();

  }

  测试Presenter

  Presenter的测试一般可以不用依赖AndroidSDK了,Presenter依赖于底层的领域服务,也依赖上层View,demo中对领域服务的依赖没有通过构造函数的方式注入,而是通过静态工厂方法构建,还是需要用到PowerMock

  配置

  通过@RunWith指定使用PowerMockRunner

  通过@PrepareForTest配置PowerMock需要模拟的静态类型

  @RunWith(PowerMockRunner.class)

  @PrepareForTest({ServiceFactory.class})

  @Before

  publicvoidsetUp(){

  PowerMockito.mockStatic(ServiceFactory.class);

  }

  成功路径用例

  验证View的方法是否成功调用且调用参数是否一致

  @Test

  publicvoidfetch_success(){

  Stringexpected="helloworld";

  SlowServiceservice=Mockito.mock(SlowService.class);

  Mockito.when(service.fetch()).thenReturn(expected);

  PowerMockito.when(ServiceFactory.create())

  .thenReturn(service);

  MainContract.Viewview=Mockito.mock(MainContract.View.class);

  MainPresenterpresenter=newMainPresenter(view,executors);

  presenter.fetch();

  Mockito.verify(service,Mockito.times(1)).fetch();

  Mockito.verify(view,Mockito.times(1)).onFetchStarted();

  Mockito.verify(view,Mockito.times(1)).onFetchCompleted();

  Mockito.verify(view,Mockito.times(0)).onFetchFailed(Mockito.anyObject());

  ArgumentCaptorcaptor=ArgumentCaptor.forClass(String.class);

  Mockito.verify(view,Mockito.times(1)).onFetchSuccess(captor.capture());

  assertEquals(expected,captor.getValue());

  }

  失败路径用例

  @Test

  publicvoidfetch_failed(){

  RuntimeExceptionexception=newRuntimeException("fetchfailed");

  SlowServiceservice=Mockito.mock(SlowService.class);

  Mockito.when(service.fetch()).thenThrow(exception);

  PowerMockito.when(ServiceFactory.create())

  .thenReturn(service);

  MainContract.Viewview=Mockito.mock(MainContract.View.class);

  MainPresenterpresenter=newMainPresenter(view,executors);

  presenter.fetch();

  Mockito.verify(service,Mockito.times(1)).fetch();

  Mockito.verify(view,Mockito.times(1)).onFetchStarted();

  Mockito.verify(view,Mockito.times(1)).onFetchCompleted();

  ArgumentCaptorcaptor=ArgumentCaptor.forClass(Throwable.class);

  Mockito.verify(view,Mockito.times(1)).onFetchFailed(captor.capture());

  assertEquals(exception,captor.getValue());

  Mockito.verify(view,Mockito.times(0)).onFetchSuccess(Mockito.anyString());

  }

  测试Service

  Service不会对上层有依赖,可以直接使用JUnit测试

  publicclassSlowServiceImplTest{

  @Test

  publicvoidfetch_data(){

  SlowServiceImplimpl=newSlowServiceImpl();

  Stringdata=impl.fetch();

  assertEquals("fromslowservice",data);

  }

  }

  自动化测试一般是在持续集成环境中使用命令来执行单元测试:gradlew:app:testDebugUnitTest

  以上就是关于扣丁学堂Android开发培训单元测试最佳实践的详细介绍,希望对同学们学习有所帮助。

相关文章

网友评论

    本文标题:扣丁学堂Android开发培训解析如何对Android原生应用进

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