BrantApps
BrantApps

Reputation: 6472

Replacing Provider injections with Mockito mocks during test with Dagger

I am attempting to test-drive a suite of changes I'm making to my Android service (android.app.Service) - I am using Dagger and Robolectric and I need to replace the field injected classes within the service with some mocks to reduce the test scope...make it (slightly) more 'unit' like.

So, the short version...

I inject Providers.of (Guice syntax there...) into my android.app.Service. How do I replace them with MockProviders during a unit test?

The longer version...

This is what the relevant service code looks like;

@Inject SpotService spotService;
@Inject Provider<SynchroniseTidePosition> syncTidePosition;
@Inject Provider<SynchroniseSwellDataTask> syncBuoyData;
@Inject Provider<SynchroniseConditionsTask> syncConditionsData;
@Inject SpotRatingCalculator spotRatingCalculator;
@Inject LocalBroadcastManager localBroadcastManager;
@Inject NotificationManager notificationManager;

/**
 * @see android.app.Service#onCreate()
 */
@Override
public void onCreate() {
  super.onCreate();
  inject(this);
...

So, under normal operation the startService(intent) call lets the service inject it's dependencies during onCreate and we're all good.

Under my test I want to replace the injected Providers get() calls with Mockito mocks. I have attempted to follow the Dagger test example and created a test module that looks like this;

@Module(includes = OceanLifeModule.class,
        injects = {TestSynchronisationServiceNotifications.class},
        overrides = true)
  static class TestSynchronisationServiceNotificationsModule {
    @Provides LocalBroadcastManager provideLocalBroadcastManager() {
      return LocalBroadcastManager.getInstance(Robolectric.application);
    }
    
    @Provides NotificationManager providesNotificationManager() {
      return (NotificationManager) Robolectric.application.getSystemService(Context.NOTIFICATION_SERVICE);
    }
    
    @Provides SpotService provideSpotService() {
      return mock(SpotService.class);
    }
    
    @Provides SpotRatingCalculator provideSpotRatingCalculator() {
      return mock(SpotRatingCalculator.class);
    }
    
    @Provides SynchroniseTidePosition provideSyncTidePosition() {
      return mock(SynchroniseTidePosition.class);
    }
    
    @Provides SynchroniseConditionsTask provideSyncConditionsTask() {
      return mock(SynchroniseConditionsTask.class);
    }
    
    @Provides SynchroniseSwellDataTask provideSyncSwellDataTask() {
      return mock(SynchroniseSwellDataTask.class);
    }
  }

I am expecting that when my actual Service code calls the Provider get() I would be getting the Mockito mocks back (those are the mocks that my test module @Provides).

This isn't happening. What's wrong with the approach I'm heading down here?

Upvotes: 8

Views: 4136

Answers (1)

Jesse Wilson
Jesse Wilson

Reputation: 40613

Make your own Providers.of():

public static <T> Provider<T> of(final T t) {
  return new Provider<T>() {
    public T get() {
      return t;
     }
  }
}

Dagger should probably include this in a testing module.

Upvotes: 3

Related Questions