Issue with Robolectric with new version of Google Play services
I use Robolectric for unit tests, I have Google Play Services in my project. This worked fine, until yesterday, when Google Play Services updated to a new version. I get this error:
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
It seems the Shadow class is not called, GooglePlayServicesUtil is called giving the NullPointerException. Has anyone seen this?
I don't even use Google Play Services in the tests.
I've added next workaround and it works fine:
Extract all PlayServices' related code to Utility class (in my case it is just Availability check):
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;
}
}
Implement shadow for this Utility class:
@Implements(PlayServicesUtils.class)
public class ShadowPlayServicesUtils {
@Implementation
@PlayServicesUtils.PlayServicesAvailability
public static int checkPlayServices(@NonNull Activity activity) {
return PlayServicesUtils.AVAILABLE;
}
}
Add shadow to your test class (or to base level test class):
@Ignore
@RunWith(TestRunner.class)
@Config(
sdk = 18,
constants = BuildConfig.class,
shadows = {
ShadowPlayServicesUtils.class
}
)
public abstract class BaseTest {
// some code, maybe
}
Add your shadow to TestRunner's InstrumentationConfiguration creation:
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();
}
}
Original answer:
I've found similar issue on Robolectric issue tracker and workaround which is provided there - works!
Just force success initialisation of Google Play Services:
@Before public void setUp() {
// force success every time
ShadowGooglePlayServicesUtil.setIsGooglePlayServicesAvailable(ConnectionResult.SUCCESS);
}
EDIT:
But there is another issue with Play Services 8.3 and 8.4. And this issue is still not fixed.
链接地址: http://www.djcxy.com/p/87448.html上一篇: 让卡夫卡消费者一次只阅读一条消息