<commit_before># DaggerMock
A JUnit rule to easily override Dagger 2 objects

[![Build Status](https://travis-ci.org/fabioCollini/DaggerMock.svg?branch=master)](https://travis-ci.org/fabioCollini/DaggerMock)
[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-DaggerMock-green.svg?style=true)](https://android-arsenal.com/details/1/2987)
[![](https://jitpack.io/v/fabioCollini/DaggerMock.svg)](https://jitpack.io/#fabioCollini/DaggerMock)

More info about testing using Dagger 2 and Mockito are available in this
[Medium post](https://medium.com/@fabioCollini/android-testing-using-dagger-2-mockito-and-a-custom-junit-rule-c8487ed01b56).

Overriding an object managed by Dagger 2 is not easy, you need to define a TestModule and, if you want
to inject your test object, a TestComponent.

Using a `DaggerMockRule` it's possible to override easily (in Java or Kotlin) the objects defined in a Dagger module:

###### Java
```java
public class MainServiceTest {

    @Rule public DaggerMockRule<MyComponent> rule = new DaggerMockRule<>(MyComponent.class, new MyModule())
            .set(new DaggerMockRule.ComponentSetter<MyComponent>() {
                @Override public void setComponent(MyComponent component) {
                    mainService = component.mainService();
                }
            });

    @Mock RestService restService;

    @Mock MyPrinter myPrinter;

    MainService mainService;

    @Test
    public void testDoSomething() {
        when(restService.getSomething()).thenReturn("abc");

        mainService.doSomething();

        verify(myPrinter).print("ABC");
    }
}
```

###### Kotlin
```kotlin
class MainServiceTest {

    @get:Rule val rule = DaggerMock.rule<MyComponent>(MyModule()) {
        set { mainService = it.mainService() }
    }

    val restService: RestService = mock()

    val myPrinter: MyPrinter = mock()

    lateinit var mainService: MainService

    @Test
    fun testDoSomething() {
        whenever(restService.something).thenReturn("abc")

        mainService.doSomething()

        verify(myPrinter).print("ABC")
    }
}
```

When `DaggerMockRule` rule is instantiated, it looks for all @Mock annotated fields in your test class
and it replaces them with Mockito mocks if there is a provider method in your module for that class.
Then it uses all the test fields to override the objects defined in the Dagger configuration.

> Note: only non static and non null fields are used by DaggerMock. Fields annotated with @Mock and @Spy can
be used because `MockitoAnnotations.initMocks` method is automatically invoked before the test.

In this example
[MyModule](https://github.com/fabioCollini/DaggerMock/blob/master/app/src/main/java/it/cosenonjaviste/daggermock/demo/MyModule.java)
contains two methods to provide `RestService` and `MyPrinter` objects. Behind the scenes, the
`DaggerMockRule` rule dynamically creates a new module that overrides `MyModule`, it returns the mocks
for `restService` and `myPrinter` defined in the test instead of the real objects, like this:

```java
public class TestModule extends MyModule {
    @Override public MyPrinter provideMyPrinter() {
        return Mockito.mock(MyPrinter.class);
    }

    @Override public RestService provideRestService() {
        return Mockito.mock(RestService.class);
    }
}
```

DaggerMock can't override Dagger objects that are defined using `Inject` annotation, since version 0.6
 you get a runtime error if the test contains a field of a class that is not defined in a module. 
All the modules containing objects that are going to be replaced must be provided in the `DaggerMockRule` constructor.

## Espresso support

A `DaggerMockRule` can also be used in an Espresso test:

###### Java
```java
public class MainActivityTest {

    @Rule public DaggerMockRule<MyComponent> daggerRule = new DaggerMockRule<>(MyComponent.class, new MyModule())
            .set(new DaggerMockRule.ComponentSetter<MyComponent>() {
                @Override public void setComponent(MyComponent component) {
                    App app = (App) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();
                    app.setComponent(component);
                }
            });

    @Rule public ActivityTestRule<MainActivity> activityRule = new ActivityTestRule<>(MainActivity.class, false, false);

    @Mock RestService restService;

    @Mock MyPrinter myPrinter;

    @Test
    public void testCreateActivity() {
        when(restService.getSomething()).thenReturn("abc");

        activityRule.launchActivity(null);

        verify(myPrinter).print("ABC");
    }
}
```

###### Kotlin
```kotlin
class MainActivityTest {

    @get:Rule val daggerRule = DaggerMock.rule<MyComponent>(MyModule()) {
        set {
            val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as App
            app.component = it
        }
    }

    @get:Rule var activityRule = ActivityTestRule(MainActivity::class.java, false, false)

    val restService: RestService = mock()

    val myPrinter: MyPrinter = mock()

    @Test fun testCreateActivity() {
        whenever(restService.something).thenReturn("abc")

        activityRule.launchActivity(null)

        verify(myPrinter).print("ABC")
    }
}
```

In this example the third parameter of `ActivityTestRule` constructor is `false` to manually launch the Activity. In this way
the behaviour of the mocks objects can be defined before the creation of the Activity. 

## Robolectric support

In a similar way a `DaggerMockRule` can be used in a Robolectric test:

###### Java
```java
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MainActivityTest {

    @Rule public final DaggerMockRule<MyComponent> rule = new DaggerMockRule<>(MyComponent.class, new MyModule())
            .set(new DaggerMockRule.ComponentSetter<MyComponent>() {
                @Override public void setComponent(MyComponent component) {<commit_msg>Improve notes in readme. Fixes #53<commit_after># DaggerMock
A JUnit rule to easily override Dagger 2 objects

[![Build Status](https://travis-ci.org/fabioCollini/DaggerMock.svg?branch=master)](https://travis-ci.org/fabioCollini/DaggerMock)
[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-DaggerMock-green.svg?style=true)](https://android-arsenal.com/details/1/2987)
[![](https://jitpack.io/v/fabioCollini/DaggerMock.svg)](https://jitpack.io/#fabioCollini/DaggerMock)

More info about testing using Dagger 2 and Mockito are available in this
[Medium post](https://medium.com/@fabioCollini/android-testing-using-dagger-2-mockito-and-a-custom-junit-rule-c8487ed01b56).

Overriding an object managed by Dagger 2 is not easy, you need to define a TestModule and, if you want
to inject your test object, a TestComponent.

Using a `DaggerMockRule` it's possible to override easily (in Java or Kotlin) the objects defined in a Dagger module:

###### Java
```java
public class MainServiceTest {

    @Rule public DaggerMockRule<MyComponent> rule = new DaggerMockRule<>(MyComponent.class, new MyModule())
            .set(new DaggerMockRule.ComponentSetter<MyComponent>() {
                @Override public void setComponent(MyComponent component) {
                    mainService = component.mainService();
                }
            });

    @Mock RestService restService;

    @Mock MyPrinter myPrinter;

    MainService mainService;

    @Test
    public void testDoSomething() {
        when(restService.getSomething()).thenReturn("abc");

        mainService.doSomething();

        verify(myPrinter).print("ABC");
    }
}
```

###### Kotlin
```kotlin
class MainServiceTest {

    @get:Rule val rule = DaggerMock.rule<MyComponent>(MyModule()) {
        set { mainService = it.mainService() }
    }

    val restService: RestService = mock()

    val myPrinter: MyPrinter = mock()

    lateinit var mainService: MainService

    @Test
    fun testDoSomething() {
        whenever(restService.something).thenReturn("abc")

        mainService.doSomething()

        verify(myPrinter).print("ABC")
    }
}
```

When `DaggerMockRule` rule is instantiated, it looks for all @Mock annotated fields in your test class
and it replaces them with Mockito mocks if there is a provider method in your module for that class.
Then it uses all the test fields to override the objects defined in the Dagger configuration.

> Note: DaggerMock invokes `MockitoAnnotations.initMocks` before the test. Hence, just adding the `DaggerMockRule`
is not enough: you additionally need to annotate any field you want to mock with `@Mock` or `@Spy` (even if you
don't have to define behavior or `verify` things on the mock).

> Note: static and null fields can't be used by DaggerMock.

In this example
[MyModule](https://github.com/fabioCollini/DaggerMock/blob/master/app/src/main/java/it/cosenonjaviste/daggermock/demo/MyModule.java)
contains two methods to provide `RestService` and `MyPrinter` objects. Behind the scenes, the
`DaggerMockRule` rule dynamically creates a new module that overrides `MyModule`, it returns the mocks
for `restService` and `myPrinter` defined in the test instead of the real objects, like this:

```java
public class TestModule extends MyModule {
    @Override public MyPrinter provideMyPrinter() {
        return Mockito.mock(MyPrinter.class);
    }

    @Override public RestService provideRestService() {
        return Mockito.mock(RestService.class);
    }
}
```

DaggerMock can't override Dagger objects that are defined using `Inject` annotation, since version 0.6
 you get a runtime error if the test contains a field of a class that is not defined in a module. 
All the modules containing objects that are going to be replaced must be provided in the `DaggerMockRule` constructor.

## Espresso support

A `DaggerMockRule` can also be used in an Espresso test:

###### Java
```java
public class MainActivityTest {

    @Rule public DaggerMockRule<MyComponent> daggerRule = new DaggerMockRule<>(MyComponent.class, new MyModule())
            .set(new DaggerMockRule.ComponentSetter<MyComponent>() {
                @Override public void setComponent(MyComponent component) {
                    App app = (App) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();
                    app.setComponent(component);
                }
            });

    @Rule public ActivityTestRule<MainActivity> activityRule = new ActivityTestRule<>(MainActivity.class, false, false);

    @Mock RestService restService;

    @Mock MyPrinter myPrinter;

    @Test
    public void testCreateActivity() {
        when(restService.getSomething()).thenReturn("abc");

        activityRule.launchActivity(null);

        verify(myPrinter).print("ABC");
    }
}
```

###### Kotlin
```kotlin
class MainActivityTest {

    @get:Rule val daggerRule = DaggerMock.rule<MyComponent>(MyModule()) {
        set {
            val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as App
            app.component = it
        }
    }

    @get:Rule var activityRule = ActivityTestRule(MainActivity::class.java, false, false)

    val restService: RestService = mock()

    val myPrinter: MyPrinter = mock()

    @Test fun testCreateActivity() {
        whenever(restService.something).thenReturn("abc")

        activityRule.launchActivity(null)

        verify(myPrinter).print("ABC")
    }
}
```

In this example the third parameter `launchActivity` of the `ActivityTestRule` constructor is set to `false` to manually
launch the Activity. This way it's possible to define behaviour on the mocks before the creation of the Activity, and
`verify` things on your mocks in your tests.

## Robolectric support

In a similar way a `DaggerMockRule` can be used in a Robolectric test:

###### Java
```java
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class MainActivityTest {

    @Rule public final DaggerMockRule<MyComponent> rule = new DaggerMockRule<>(MyComponent.class, new MyModule())
            .set(new DaggerMockRule.ComponentSetter<MyComponent>() {
                @Override public void setComponent(MyComponent component) {
{'fraction_non_alphanumeric': 0.09868796349115802, 'fraction_numerical': 0.00391166164126803, 'mean_word_length': 3.7825409197194078, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 32, 'https://': 16, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3535289', 'n_tokens_mistral': 3551, 'n_tokens_neox': 3354, 'n_words': 1060}