I'm a complete beginner when it comes to testing and my current task is to fix an issue that stops already existing tests from running.
Several tests using Robolectric are failing with the error message
java.util.ServiceConfigurationError: org.robolectric.internal.ShadowProvider: Provider org.robolectric.Shadows not a subtype
at java.util.ServiceLoader.fail(ServiceLoader.java:239)
at java.util.ServiceLoader.access$300(ServiceLoader.java:185)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:376)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
I read in this Github post that this error can happen if there are issues with the environment configuration. After some testing I could narrow down the problem to two methods in the Application class, initPicasso and initJobDispatcher, which initialize Picasso and a Firebase job that is running now and then
public class MyApplication extends Application {
private ApplicationComponent applicationComponent;
@Override
public void onCreate() {
super.onCreate();
Timber.plant(new Timber.DebugTree());
AndroidThreeTen.init(this);
Fabric.with(this, new Crashlytics());
initPicasso();
applicationComponent = DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build();
initJobDispatcher();
}
void initPicasso() {
final String PICASSO_CACHE = "picasso-cache";
File cacheDir = new File(getApplicationContext().getCacheDir(), PICASSO_CACHE);
if (!cacheDir.exists()) {
//noinspection ResultOfMethodCallIgnored
cacheDir.mkdirs();
}
Cache cache = new Cache(cacheDir, 50 * 1024 * 1024);
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Timber.d("XYZ" + message);
}
});
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(httpLoggingInterceptor)
.cache(cache)
.build();
Picasso.setSingletonInstance(
new Picasso.Builder(this)
.listener(new Picasso.Listener() {
@Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
}
})
.downloader(new OkHttp3Downloader(client))
.build()
);
}
void initJobDispatcher() {
Driver myDriver = new GooglePlayDriver(this);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(myDriver);
Timber.d("Setting up Job at: %s", LocalDateTime.now().toString());
Job job = dispatcher.newJobBuilder()
.setService(SyncJobService.class)
.setTag("my-job-tag")
.setConstraints(Constraint.ON_ANY_NETWORK)
.setTrigger(Trigger.executionWindow(15, 25))
.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
.setRecurring(false)
.build();
int result = dispatcher.schedule(job);
if (result != FirebaseJobDispatcher.SCHEDULE_RESULT_SUCCESS) {
Timber.e("Job could not be scheduled: %d", result);
}
}
public ApplicationComponent getApplicationComponent() {
return applicationComponent;
}
}
If I comment out these two methods, the tests will run fine.
Now my question is: How can I mock the Application class or at least these two methods? I tried to create a test Application class which overrides these methods, but that didn't help.
public class MyApplicationTest extends Application {
void initPicasso() {
//do nothing here
System.out.println("Using the MyApplicationTest application");
}
void initJobDispatcher() {
//do nothing here
}
}
Or as this project is using Dagger2, are there ways using dagger to mock the Application class? As this area is absolutely new to me, any advices or suggestions would be greatly appreciated.
Aucun commentaire:
Enregistrer un commentaire