Robolectric 新版本 Google Play 服务出现问题
Issue with Robolectric with new version of Google Play services
我使用 Robolectric 进行单元测试,我的项目中有 Google Play 服务。直到昨天 Google Play Services 更新到新版本时,它才正常工作。我收到此错误:
java.lang.NullPointerException
at com.google.android.gms.common.GooglePlayServicesUtil.zzh(Unknown Source)
at com.google.android.gms.common.GooglePlayServicesUtil.zzd(Unknown Source)
at com.google.android.gms.common.GoogleApiAvailability.isGooglePlayServicesAvailable(Unknown Source)
at com.google.android.gms.common.api.zzg$zze.zznn(Unknown Source)
at com.google.android.gms.common.api.zzg$zzi.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Process finished with exit code 255
似乎没有调用 Shadow class,GooglePlayServicesUtil 被调用并给出了 NullPointerException。有人看过吗?
我什至不在测试中使用 Google Play 服务。
我已经添加了下一个解决方法,它工作正常:
将所有 PlayServices' 相关代码提取到实用程序 class(在我的例子中,它只是可用性检查):
public class PlayServicesUtils {
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
public static final int AVAILABLE = 1;
public static final int ERROR_RESOLVABLE = 2;
public static final int ERROR_UNRESOLVABLE = 3;
@IntDef({AVAILABLE, ERROR_RESOLVABLE, ERROR_UNRESOLVABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface PlayServicesAvailability {
}
@PlayServicesAvailability
public static int checkPlayServices(@NonNull Activity activity) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(activity);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST).show();
return PlayServicesUtils.ERROR_RESOLVABLE;
} else {
CLog.e(Constants.TAG, "This device does not support Google Play services.");
return PlayServicesUtils.ERROR_UNRESOLVABLE;
}
}
return PlayServicesUtils.AVAILABLE;
}
}
为此实用程序实施影子 class:
@Implements(PlayServicesUtils.class)
public class ShadowPlayServicesUtils {
@Implementation
@PlayServicesUtils.PlayServicesAvailability
public static int checkPlayServices(@NonNull Activity activity) {
return PlayServicesUtils.AVAILABLE;
}
}
将阴影添加到您的测试 class(或添加到基础级别测试 class):
@Ignore
@RunWith(TestRunner.class)
@Config(
sdk = 18,
constants = BuildConfig.class,
shadows = {
ShadowPlayServicesUtils.class
}
)
public abstract class BaseTest {
// some code, maybe
}
将您的影子添加到 TestRunner 的 InstrumentationConfiguration 创建中:
public class TestRunner extends RobolectricGradleTestRunner {
public TestRunner(Class<?> klass) throws InitializationError {
super(klass);
}
@Override
public InstrumentationConfiguration createClassLoaderConfig() {
InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder();
builder.addInstrumentedClass(PlayServicesUtils.class.getName());
return builder.build();
}
}
原回答:
我在 Robolectric 问题跟踪器上找到了 similar issue,那里提供了解决方法 - 有效!
只需强制 Google Play 服务初始化成功:
@Before public void setUp() {
// force success every time
ShadowGooglePlayServicesUtil.setIsGooglePlayServicesAvailable(ConnectionResult.SUCCESS);
}
编辑:
但还有另一个 issue 与 Play Services 8.3 和 8.4。而且这个问题还没有解决。
我使用 Robolectric 进行单元测试,我的项目中有 Google Play 服务。直到昨天 Google Play Services 更新到新版本时,它才正常工作。我收到此错误:
java.lang.NullPointerException
at com.google.android.gms.common.GooglePlayServicesUtil.zzh(Unknown Source)
at com.google.android.gms.common.GooglePlayServicesUtil.zzd(Unknown Source)
at com.google.android.gms.common.GoogleApiAvailability.isGooglePlayServicesAvailable(Unknown Source)
at com.google.android.gms.common.api.zzg$zze.zznn(Unknown Source)
at com.google.android.gms.common.api.zzg$zzi.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Process finished with exit code 255
似乎没有调用 Shadow class,GooglePlayServicesUtil 被调用并给出了 NullPointerException。有人看过吗?
我什至不在测试中使用 Google Play 服务。
我已经添加了下一个解决方法,它工作正常:
将所有 PlayServices' 相关代码提取到实用程序 class(在我的例子中,它只是可用性检查):
public class PlayServicesUtils { private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000; public static final int AVAILABLE = 1; public static final int ERROR_RESOLVABLE = 2; public static final int ERROR_UNRESOLVABLE = 3; @IntDef({AVAILABLE, ERROR_RESOLVABLE, ERROR_UNRESOLVABLE}) @Retention(RetentionPolicy.SOURCE) public @interface PlayServicesAvailability { } @PlayServicesAvailability public static int checkPlayServices(@NonNull Activity activity) { GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); int resultCode = apiAvailability.isGooglePlayServicesAvailable(activity); if (resultCode != ConnectionResult.SUCCESS) { if (apiAvailability.isUserResolvableError(resultCode)) { apiAvailability.getErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST).show(); return PlayServicesUtils.ERROR_RESOLVABLE; } else { CLog.e(Constants.TAG, "This device does not support Google Play services."); return PlayServicesUtils.ERROR_UNRESOLVABLE; } } return PlayServicesUtils.AVAILABLE; } }
为此实用程序实施影子 class:
@Implements(PlayServicesUtils.class) public class ShadowPlayServicesUtils { @Implementation @PlayServicesUtils.PlayServicesAvailability public static int checkPlayServices(@NonNull Activity activity) { return PlayServicesUtils.AVAILABLE; } }
将阴影添加到您的测试 class(或添加到基础级别测试 class):
@Ignore @RunWith(TestRunner.class) @Config( sdk = 18, constants = BuildConfig.class, shadows = { ShadowPlayServicesUtils.class } ) public abstract class BaseTest { // some code, maybe }
将您的影子添加到 TestRunner 的 InstrumentationConfiguration 创建中:
public class TestRunner extends RobolectricGradleTestRunner { public TestRunner(Class<?> klass) throws InitializationError { super(klass); } @Override public InstrumentationConfiguration createClassLoaderConfig() { InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder(); builder.addInstrumentedClass(PlayServicesUtils.class.getName()); return builder.build(); } }
原回答:
我在 Robolectric 问题跟踪器上找到了 similar issue,那里提供了解决方法 - 有效!
只需强制 Google Play 服务初始化成功:
@Before public void setUp() {
// force success every time
ShadowGooglePlayServicesUtil.setIsGooglePlayServicesAvailable(ConnectionResult.SUCCESS);
}
编辑:
但还有另一个 issue 与 Play Services 8.3 和 8.4。而且这个问题还没有解决。