Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 617
BrantApps Avatar asked Jul 31 '13 22:07

BrantApps


People also ask

How to inject mocks in Mockito?

Mockito @InjectMocks annotations allow us to inject mocked dependencies in the annotated class mocked object. This is useful when we have external dependencies in the class we want to mock. We can specify the mock objects to be injected using @Mock or @Spy annotations.

Why we use@ InjectMocks?

@InjectMocks is the Mockito Annotation. It allows you to mark a field on which an injection is to be performed. Injection allows you to, Enable shorthand mock and spy injections.

What can be mocked with Mockito?

We can use Mockito class mock() method to create a mock object of a given class or interface. This is the simplest way to mock an object. We are using JUnit 5 to write test cases in conjunction with Mockito to mock objects.

What is stubbing in Mockito?

A stub is a fake class that comes with preprogrammed return values. It's injected into the class under test to give you absolute control over what's being tested as input. A typical stub is a database connection that allows you to mimic any scenario without having a real database.


1 Answers

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.

like image 190
Jesse Wilson Avatar answered Oct 07 '22 19:10

Jesse Wilson