是否有一种运行时检查方式,可以让应用程序判断它是否作为插桩测试的一部分运行?
背景:我们的应用程序在启动时执行数据库同步。但只有正常启动时才需要进行此操作。这会干扰数据库同步测试的插桩测试,这并不令人意外。
对于所有其他测试,这都是浪费CPU周期。
是否有一种运行时检查方式,可以让应用程序判断它是否作为插桩测试的一部分运行?
背景:我们的应用程序在启动时执行数据库同步。但只有正常启动时才需要进行此操作。这会干扰数据库同步测试的插桩测试,这并不令人意外。
对于所有其他测试,这都是浪费CPU周期。
一种更简单的解决方案是检查一个只会出现在测试类路径中的类,它可以与JUnit 4配合使用(不像使用ActivityUnitTestCase的解决方案),并且不需要发送自定义意图到您的活动/服务(在某些情况下甚至可能不可能)。
private boolean isTesting() {
try {
Class.forName("com.company.SomeTestClass");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
public boolean isUnitTest() {
String device = Build.DEVICE;
String product = Build.PRODUCT;
if (device == null) {
device = "";
}
if (product == null) {
product = "";
}
return device.equals("robolectric") && product.equals("robolectric");
}
ActivityManager.isRunningInUserTestHarness()
(但值得注意的是,它仅在API 29
中可用,甚至不在support/androidx库中)。 - Top-Masterhttp://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-3/
setApplication
方法,而简单的AndroidTestCase
没有。但是它们似乎仍然可以正常运行。总之,这似乎是唯一的问题。谢谢。 - Martind = (◕‿↼) 很好的回答, 但是如果一些库开发者(比如我)想知道主机(或使用该库的应用程序)是否正在进行测试,则可以尝试:
import android.content.pm.ApplicationInfo;
// ...
private static int wasTestRun = 0xDEAD;
/**
* Should only be used to speed up testing (no behavior change).
* @return true in tests, if Gradle has the right dependencies.
*/
public static boolean isTestRun(@NonNull Context context) {
if (wasTestRun != 0xDEAD) {
return wasTestRun != 0;
}
// Ignore release builds (as App may be using JUnit by mistake).
if (isDebuggable(context)) {
try {
Class.forName("org.junit.runner.Runner");
wasTestRun = 1;
return true;
} catch (ClassNotFoundException ignored) {
}
}
wasTestRun = 0;
return false;
}
public static boolean isDebuggable(@Nullable Context context) {
return context != null && (context.getApplicationContext()
.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}
public void setUp() throws Exception {
super.setUp();
Intent activityIntent = new Intent();
activityIntent.putExtra("testMode", true);
setActivityIntent(activityIntent);
}
2) 在您的活动中,检查 testMode:
Bundle extras = getIntent().getExtras();
if (extras != null && extras.getBoolean("testMode")) {
// disable your database sync
}
if (isRunningTest == null) {
isRunningTest = false;
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
List<StackTraceElement> list = Arrays.asList(stackTrace);
for (StackTraceElement element : list) {
if (element.getClassName().startsWith("androidx.test.runner.MonitoringInstrumentation")) {
isRunningTest = true;
break;
}
}
}
这对我有效,因为没有实际设备在运行
public static boolean isUnitTest() {
return Build.BRAND.startsWith(Build.UNKNOWN) && Build.DEVICE.startsWith(Build.UNKNOWN) && Build.DEVICE.startsWith(Build.UNKNOWN) && Build.PRODUCT.startsWith(Build.UNKNOWN);
}