Android 单元测试参考代码

961 阅读2分钟

写在前面

Android 的单元测试如何进行配置,在网络上有大量的文章去介绍,这里不再重复。

但是单元测试并不是光配置起来就完事了的,如何真正地测试一些实际的点,是这篇记录需要重点关注的事情。

如何检查 Activity 有没有通过 startActivity 启动另一个 Activity

// 当前使用 robolectric 版本: 4.2

ShadowActivity shadowActivity = Shadows.shadowOf(activity);

// ..执行 startForActivity..

Intent intent = shadowActivity.peekNextStartedActivityForResult().intent;
assertEquals(intent.getComponent().getClassName(), NextActivity.class.getName());
// 这里还可以对 intent 中的数据进行进一步的测试,此处略过

如何模拟 Activity 的生命周期

// launch 的时候,默认就执行了 create -> start -> resume,最后处在 RESUMED
// 如果你在 onCreate 里面就 finish 了,那 launch 完成,就会是 DESTROYED
try (ActivityScenario<YourActivity> scenario = ActivityScenario.launch(YourActivity.class)) {
			scenario.onActivity(activity -> {
				// 执行 pause
				scenario.moveToState(Lifecycle.State.STARTED);

				// 执行 stop
				scenario.moveToState(Lifecycle.State.CREATED);

				// 执行 destroy
				scenario.moveToState(Lifecycle.State.DESTROYED);
			});
		}

如何在启动 Activity 的时候,通过 Intent 传递参数

Intent launchIntent = new Intent(ApplicationProvider.getApplicationContext(), YourActivity.class);
launchIntent.putExtra("key", "value");
try (ActivityScenario<YourActivity> scenario = ActivityScenario.launch(launchIntent)) {
			scenario.onActivity(activity -> {
				// blablabla
			});
		}

如何使用 Mockito 来 mock 静态方法

mockito 在 3.5.0 之后,可以对静态方法进行 mock,只要依赖 mockito-inline 即可

javadoc.io/doc/org.moc…

try (MockedStatic<YourClass> mockYourClassStatic = Mockito.mockStatic(YourClass.class)) {
  mockYourClassStatic.when(() -> YourClass.staticMethod()).thenReturn("mockResult");
  // 这个还可以 verify
  mockYourClassStatic.verify(() -> YourClass.staticMethod2());
}

注意,这个作用域仅限当前线程

如何将一个单例替换为 mock 或者 spy

通常,我们会将单例替换为 mock 对象,以便于他在后面的程序中,返回我们想要的值

或者,我们会将它替换为 spy 对象,这样就可以用来进行 verify 或者部分 mock

// 先创建真实的,再 mock getInstance,用 spy 去作为返回值返回
YourClass yourClass = YourClass.getIntance();
YourClass spyYourClass = Mockito.spy(yourClass);
MockedStatic<YourClass> mockStaticYourClass = Mockito.mockStatic(YourClass.class);
mockStaticYourClass.when(() -> YourClass.getIntance()).thenReturn(spyYourClass);

// 返回 mock 的话,只要在 thenReturn 中,返回 mock 对象即可,此处不再赘述

如何让单元测试延时

有一个 case 是,有一个 button 上在点击事件发生的时候,做了防抖动的处理,他使用的方式是,调用 SystemClock.elapsedRealtime()来获取时间,和 last 时间进行对比,超过阈值才可以点。

所以在这个 case 中,界面刚起来的时候,实际上是有非常短的时间,这个按钮是点不了的,只是用户是碰不到这种状况的。

那么我们可以用 Robolectric 对 UnitTest 进行时间的指定,使用下列代码

Robolectric.getForegroundThreadScheduler().advanceTo(1500);

如何让 RxJava 异步转同步

这里用的还是 RxJava 1,emmm

RxJavaPlugins.getInstance().registerSchedulersHook(new RxJavaSchedulersHook() {
	@Override
	public Scheduler getIOScheduler() {
		return Schedulers.trampoline();
	}
});

RxAndroidPlugins.getInstance().registerSchedulersHook(new RxAndroidSchedulersHook() {
	@Override
	public Scheduler getMainThreadScheduler() {
		return Schedulers.immediate();
	}
});

如何在使用 Mockito mock 方法的时候,获取传入的参数

when(yourMock.func(any(), any())).then(new Answer<Object>() {
			@Override
			public Object answer(InvocationOnMock invocation) throws Throwable {
				int arg1 = invocation.getArgument(0);
				String arg2 = invocation.getArgument(1);
				return null;
			}
		});

如何使用 Mockito 去 mock 一个返回 void 的方法

doAnswer(answer).when(mockObject).voidMethod();

(未完待续)