Martin
Martin

Reputation: 24308

Roboguice and mocks: How to have roboguice inject a mock service when testing but use the REAL otherwise?

Just got my feet wet with roboguice, i like it!

I have quite a lot of methods that depend on a DB and LocationManger etc hence when i am testing these it uses the real objects, i would like to mock these objects so that when i am testing i don't have to depend on anything.

I also have been using mockito but i am unsure how i could go about this?

I know the android system comes with various mocks but i think it would be better to roll my own with mockito?

In either case i need to inject them when testing.

Anyone have any ideas on this?

Thanks in advance

Upvotes: 4

Views: 2442

Answers (3)

emmby
emmby

Reputation: 100464

Take a look at https://github.com/roboguice/roboguice/blob/master/astroboy/src/test/java/org/roboguice/astroboy/controller/Astroboy2Test.java which uses Modules.override() to override the default module with some test-specific configurations.

@Before
public void setup() {
    // Override the default RoboGuice module
    RoboGuice.setBaseApplicationInjector(Robolectric.application, RoboGuice.DEFAULT_STAGE, Modules.override(RoboGuice.newDefaultRoboModule(Robolectric.application)).with(new MyTestModule()));
    // For roboguice 4.0 and robolectric 3.1.2
    RoboGuice.getOrCreateBaseApplicationInjector(RuntimeEnvironment.application, RoboGuice.DEFAULT_STAGE, Modules.override(RoboGuice.newDefaultRoboModule(RuntimeEnvironment.application)).with(new MyTestModule()));
}

Upvotes: 4

user3346281
user3346281

Reputation: 1

@Martin: As Paul says you can inject your test location manager with Robolectric and Roboguice. However I think it's better if mocking with Mockito, this post is good for starting. You create a Mocked object and bind it to your interface. You can find also example with mocking and injecting.

Upvotes: 0

Paul D'Ambra
Paul D'Ambra

Reputation: 7814

Just to expand on this as it was the top hit while I was looking for it...

Once you've set your test class (or test runner) to override the default RoboGuice module then set your overriden RoboGuice Module as (in this instance)

public class TestModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(LocationManager.class).toInstance((LocationManager) Robolectric.application.getSystemService(Context.LOCATION_SERVICE));
    }
}

Then RoboGuice will inject the same location manager in your tests as in your application. And you can instantiate a shadow of it and set the expected location, provider state, etc.

@Test
public void mapLoadsCenteredOnPhoneLocationWhenNoTargetIntent() {
    Location l = new Location("test");
    l.setLatitude(Double.parseDouble("52.222"));
    l.setLongitude(Double.parseDouble("-2.222"));
    shadowLocationManager.setLastKnownLocation(GPS_PROVIDER, l);
    shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true);
    shadowLocationManager.setProviderEnabled(NETWORK_PROVIDER, false);
            //snip
}

Upvotes: 3

Related Questions