{"id":13991595,"url":"https://github.com/fabioCollini/DaggerMock","last_synced_at":"2025-07-22T14:31:18.113Z","repository":{"id":140972541,"uuid":"48641480","full_name":"fabioCollini/DaggerMock","owner":"fabioCollini","description":"A JUnit rule to easily override Dagger 2 objects","archived":false,"fork":false,"pushed_at":"2023-02-01T09:31:05.000Z","size":496,"stargazers_count":1160,"open_issues_count":33,"forks_count":91,"subscribers_count":33,"default_branch":"master","last_synced_at":"2024-11-29T11:37:14.526Z","etag":null,"topics":["android","dagger","espresso","junit-rule","mockito","testing"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fabioCollini.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2015-12-27T10:40:55.000Z","updated_at":"2024-11-02T04:34:16.000Z","dependencies_parsed_at":"2023-06-29T06:00:46.072Z","dependency_job_id":null,"html_url":"https://github.com/fabioCollini/DaggerMock","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/fabioCollini/DaggerMock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabioCollini%2FDaggerMock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabioCollini%2FDaggerMock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabioCollini%2FDaggerMock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabioCollini%2FDaggerMock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fabioCollini","download_url":"https://codeload.github.com/fabioCollini/DaggerMock/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fabioCollini%2FDaggerMock/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266510316,"owners_count":23940637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","dagger","espresso","junit-rule","mockito","testing"],"created_at":"2024-08-09T14:01:28.402Z","updated_at":"2025-07-22T14:31:17.734Z","avatar_url":"https://github.com/fabioCollini.png","language":"Java","readme":"# DaggerMock\nA JUnit rule to easily override Dagger 2 objects\n\n[![Build Status](https://travis-ci.org/fabioCollini/DaggerMock.svg?branch=master)](https://travis-ci.org/fabioCollini/DaggerMock)\n[![codecov](https://codecov.io/gh/fabioCollini/DaggerMock/branch/master/graph/badge.svg)](https://codecov.io/gh/fabioCollini/DaggerMock)\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-DaggerMock-green.svg?style=true)](https://android-arsenal.com/details/1/2987)\n[![](https://jitpack.io/v/fabioCollini/DaggerMock.svg)](https://jitpack.io/#fabioCollini/DaggerMock)\n\nMore info about testing using Dagger 2 and Mockito are available in this\n[Medium post](https://medium.com/@fabioCollini/android-testing-using-dagger-2-mockito-and-a-custom-junit-rule-c8487ed01b56).\n\nOverriding an object managed by Dagger 2 is not easy, you need to define a TestModule and, if you want\nto inject your test object, a TestComponent.\n\nUsing a `DaggerMockRule` it's possible to override easily (in Java or Kotlin) the objects defined in a Dagger module:\n\n###### Java\n```java\npublic class MainServiceTest {\n\n    @Rule public DaggerMockRule\u003cMyComponent\u003e rule = new DaggerMockRule\u003c\u003e(MyComponent.class, new MyModule())\n            .set(new DaggerMockRule.ComponentSetter\u003cMyComponent\u003e() {\n                @Override public void setComponent(MyComponent component) {\n                    mainService = component.mainService();\n                }\n            });\n\n    @Mock RestService restService;\n\n    @Mock MyPrinter myPrinter;\n\n    MainService mainService;\n\n    @Test\n    public void testDoSomething() {\n        when(restService.getSomething()).thenReturn(\"abc\");\n\n        mainService.doSomething();\n\n        verify(myPrinter).print(\"ABC\");\n    }\n}\n```\n\n###### Kotlin\n```kotlin\nclass MainServiceTest {\n\n    @get:Rule val rule = DaggerMock.rule\u003cMyComponent\u003e(MyModule()) {\n        set { mainService = it.mainService() }\n    }\n\n    val restService: RestService = mock()\n\n    val myPrinter: MyPrinter = mock()\n\n    lateinit var mainService: MainService\n\n    @Test\n    fun testDoSomething() {\n        whenever(restService.something).thenReturn(\"abc\")\n\n        mainService.doSomething()\n\n        verify(myPrinter).print(\"ABC\")\n    }\n}\n```\n\nWhen `DaggerMockRule` rule is instantiated, it looks for all @Mock annotated fields in your test class\nand it replaces them with Mockito mocks if there is a provider method in your module for that class.\nThen it uses all the test fields to override the objects defined in the Dagger configuration.\n\n\u003e Note: DaggerMock invokes `MockitoAnnotations.initMocks` before the test. Hence, just adding the `DaggerMockRule`\nis not enough: you additionally need to annotate any field you want to mock with `@Mock` or `@Spy` (even if you\ndon't have to define behavior or `verify` things on the mock).\n\n\u003e Note: static and null fields can't be used by DaggerMock.\n\nIn this example\n[MyModule](https://github.com/fabioCollini/DaggerMock/blob/master/app/src/main/java/it/cosenonjaviste/daggermock/demo/MyModule.java)\ncontains two methods to provide `RestService` and `MyPrinter` objects. Behind the scenes, the\n`DaggerMockRule` rule dynamically creates a new module that overrides `MyModule`, it returns the mocks\nfor `restService` and `myPrinter` defined in the test instead of the real objects, like this:\n\n```java\npublic class TestModule extends MyModule {\n    @Override public MyPrinter provideMyPrinter() {\n        return Mockito.mock(MyPrinter.class);\n    }\n\n    @Override public RestService provideRestService() {\n        return Mockito.mock(RestService.class);\n    }\n}\n```\n\nDaggerMock can't override Dagger objects that are defined using `Inject` annotation, since version 0.6\n you get a runtime error if the test contains a field of a class that is not defined in a module. \nAll the modules containing objects that are going to be replaced must be provided in the `DaggerMockRule` constructor.\n\n## Espresso support\n\nA `DaggerMockRule` can also be used in an Espresso test:\n\n###### Java\n```java\npublic class MainActivityTest {\n\n    @Rule public DaggerMockRule\u003cMyComponent\u003e daggerRule = new DaggerMockRule\u003c\u003e(MyComponent.class, new MyModule())\n            .set(new DaggerMockRule.ComponentSetter\u003cMyComponent\u003e() {\n                @Override public void setComponent(MyComponent component) {\n                    App app = (App) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();\n                    app.setComponent(component);\n                }\n            });\n\n    @Rule public ActivityTestRule\u003cMainActivity\u003e activityRule = new ActivityTestRule\u003c\u003e(MainActivity.class, false, false);\n\n    @Mock RestService restService;\n\n    @Mock MyPrinter myPrinter;\n\n    @Test\n    public void testCreateActivity() {\n        when(restService.getSomething()).thenReturn(\"abc\");\n\n        activityRule.launchActivity(null);\n\n        verify(myPrinter).print(\"ABC\");\n    }\n}\n```\n\n###### Kotlin\n```kotlin\nclass MainActivityTest {\n\n    @get:Rule val daggerRule = DaggerMock.rule\u003cMyComponent\u003e(MyModule()) {\n        set {\n            val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as App\n            app.component = it\n        }\n    }\n\n    @get:Rule var activityRule = ActivityTestRule(MainActivity::class.java, false, false)\n\n    val restService: RestService = mock()\n\n    val myPrinter: MyPrinter = mock()\n\n    @Test fun testCreateActivity() {\n        whenever(restService.something).thenReturn(\"abc\")\n\n        activityRule.launchActivity(null)\n\n        verify(myPrinter).print(\"ABC\")\n    }\n}\n```\n\nIn this example the third parameter `launchActivity` of the `ActivityTestRule` constructor is set to `false` to manually\nlaunch the Activity. This way it's possible to define behaviour on the mocks before the creation of the Activity, and\n`verify` things on your mocks in your tests.\n\n## Robolectric support\n\nIn a similar way a `DaggerMockRule` can be used in a Robolectric test:\n\n###### Java\n```java\n@RunWith(RobolectricGradleTestRunner.class)\n@Config(constants = BuildConfig.class, sdk = 21)\npublic class MainActivityTest {\n\n    @Rule public final DaggerMockRule\u003cMyComponent\u003e rule = new DaggerMockRule\u003c\u003e(MyComponent.class, new MyModule())\n            .set(new DaggerMockRule.ComponentSetter\u003cMyComponent\u003e() {\n                @Override public void setComponent(MyComponent component) {\n                    ((App) RuntimeEnvironment.application).setComponent(component);\n                }\n            });\n\n    @Mock RestService restService;\n\n    @Mock MyPrinter myPrinter;\n\n    @Test\n    public void testCreateActivity() {\n        when(restService.getSomething()).thenReturn(\"abc\");\n\n        Robolectric.setupActivity(MainActivity.class);\n\n        verify(myPrinter).print(\"ABC\");\n    }\n}\n```\n\n###### Kotlin\n```kotlin\n@RunWith(RobolectricTestRunner::class)\n@Config(constants = BuildConfig::class, sdk = intArrayOf(21))\nclass MainActivityTest {\n\n    @get:Rule val rule = DaggerMock.rule\u003cMyComponent\u003e(MyModule()) {\n        set { (RuntimeEnvironment.application as App).component = it }\n    }\n\n    val restService: RestService = mock()\n\n    val myPrinter: MyPrinter = mock()\n\n    @Test fun testCreateActivity() {\n        whenever(restService.something).thenReturn(\"abc\")\n\n        Robolectric.setupActivity(MainActivity::class.java)\n\n        verify(myPrinter).print(\"ABC\")\n    }\n}\n```\n\n\u003e Note for Linux and Mac Users: working directory must be manually configured in Android Studio. More info on [Robolectric site](http://robolectric.org/getting-started/).\n\n\n## InjectFromComponent annotation\n\nIn the first example we have used a ComponentSetter subclass to retrieve an object from the component: \n\n```java\n@Rule public DaggerMockRule\u003cMyComponent\u003e rule = new DaggerMockRule\u003c\u003e(MyComponent.class, new MyModule())\n        .set(new DaggerMockRule.ComponentSetter\u003cMyComponent\u003e() {\n            @Override public void setComponent(MyComponent component) {\n                mainService = component.mainService();\n            }\n        });\n\nMainService mainService;\n```\n\nSince DaggerMock 0.6 this code can be written in an easier way using `InjectFromComponent` annotation:\n\n###### Java\n```java\npublic class MainServiceTest {\n\n    @Rule public final DaggerMockRule\u003cMyComponent\u003e rule = new DaggerMockRule\u003c\u003e(MyComponent.class, new MyModule());\n\n    @Mock RestService restService;\n\n    @Mock MyPrinter myPrinter;\n\n    @InjectFromComponent MainService mainService;\n\n    @Test\n    public void testDoSomething() {\n        when(restService.getSomething()).thenReturn(\"abc\");\n\n        mainService.doSomething();\n\n        verify(myPrinter).print(\"ABC\");\n    }\n}\n```\n\n###### Kotlin\n```kotlin\nclass MainServiceTest {\n\n    @get:Rule val rule = DaggerMock.rule\u003cMyComponent\u003e(MyModule())\n\n    val restService: RestService = mock()\n\n    val myPrinter: MyPrinter = mock()\n\n    @InjectFromComponent lateinit var mainService: MainService\n\n    @Test fun testDoSomething() {\n        whenever(restService.something).thenReturn(\"abc\")\n\n        mainService.doSomething()\n\n        verify(myPrinter).print(\"ABC\")\n    }\n}\n```\n\nMany objects managed by Dagger are only injected in other objects and are not exposed in a component.\nFor example if the MainService object is injected in MainActivity we can use the following annotation:\n\n```java\n@InjectFromComponent(MainActivity.class) MainService mainService;\n```\n\nA MainActivity object is created using reflection, the inject method is invoked on this object and then\nthe mainService field is extracted and used to populate the test field. \n\n## Custom rules\n\nIt's easy to create a `DaggerMockRule` subclass to avoid copy and paste and simplify the test code:\n\n```java\npublic class MyRule extends DaggerMockRule\u003cMyComponent\u003e {\n    public MyRule() {\n        super(MyComponent.class, new MyModule());\n        set(new DaggerMockRule.ComponentSetter\u003cMyComponent\u003e() {\n            @Override public void setComponent(MyComponent component) {\n                App app = (App) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();\n                app.setComponent(component);\n            }\n        });\n    }\n}\n```\n\nIn Kotlin a method that creates the rule can be easily defined:\n\n```kotlin\nfun myRule() =\n        DaggerMock.rule\u003cMyComponent\u003e(MyModule()) {\n            set {\n                val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as App\n                app.component = it\n            }\n        }\n```\n\n\nThe final test uses the rule subclass:\n\n```java\npublic class MainActivityTest {\n\n    @Rule public MyRule daggerRule = new MyRule();\n\n    @Rule public ActivityTestRule\u003cMainActivity\u003e activityRule = new ActivityTestRule\u003c\u003e(MainActivity.class, false, false);\n\n    @Mock RestService restService;\n\n    @Mock MyPrinter myPrinter;\n\n    @Test\n    public void testCreateActivity() {\n        when(restService.getSomething()).thenReturn(\"abc\");\n\n        activityRule.launchActivity(null);\n\n        verify(myPrinter).print(\"ABC\");\n    }\n}\n```\n\n## Supported Dagger features\n\n### Subcomponents\n\nSince version 0.6 Dagger subcomponents are supported by DaggerMock with a limitation:\nsubcomponent module must be passed as parameter in subcomponent creation method.\nFor example if the subcomponent is defined as follows:\n\n```java\n@Subcomponent(modules = MainActivityModule.class)\npublic interface MainActivityComponent {\n    void inject(MainActivity mainActivity);\n}\n```\n\nThe method in the main component that creates the subcomponent must be defined using a module parameter: \n\n```java\n@Singleton\n@Component(modules = AppModule.class)\npublic interface AppComponent {\n    MainActivityComponent activityComponent(MainActivityModule module);\n}\n```\n\nSubcomponent support doesn't work on Dagger 2.0, you need to use Dagger version 2.1+.\nA complete example is available [here](https://github.com/fabioCollini/DaggerMock/tree/master/RealWorldApp).\n\n### Abstract and static methods in module\n\nDaggerMock doesn't support modules with static or abstract methods (annotated with `@Binds`). However if a component contains multiple modules (some abstract and other not abstract) DaggerMock can be used to replace objects defined in the not abstract modules.\n\n### Dagger Android\n\nDagger Android is supported with some limitations:\n\n - JVM tests are not supported, DaggerMock can be used only in Espresso tests\n - objects defined in subcomponent/dependent component cannot be replaced, DaggerMock works only for objects defined in application component\n - application must be set manually using `customizeBuilder` method:\n\n###### Java\n```java\npublic class EspressoDaggerMockRule extends DaggerMockRule\u003cAppComponent\u003e {\n    public EspressoDaggerMockRule() {\n        super(AppComponent.class, new AppModule());\n        customizeBuilder(new BuilderCustomizer\u003cAppComponent.Builder\u003e() {\n            @Override public AppComponent.Builder customize(AppComponent.Builder builder) {\n                return builder.application(getApp());\n            }\n        });\n        set(new DaggerMockRule.ComponentSetter\u003cAppComponent\u003e() {\n            @Override public void setComponent(AppComponent component) {\n                component.inject(getApp());\n            }\n        });\n    }\n\n    private static App getApp() {\n        return (App) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();\n    }\n}\n```\n\n###### Kotlin\n```kotlin\nfun espressoDaggerMockRule() = DaggerMock.rule\u003cAppComponent\u003e(AppModule(app)) {\n    set { component -\u003e component.inject(app) }\n    customizeBuilder\u003cAppComponent.Builder\u003e { it.application(app) }\n}\n\nval app: App get() = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as App\n```\n\nA complete example is available [here](https://github.com/fabioCollini/DaggerMock/tree/master/RealWorldAppInjector).\n\n## Kotlin support\n\nDaggerMock can be used in both Java and Kotlin projects. Kotlin classes are final by default, you need to\n _open_ them to create mocks using Mockito (and to use DaggerMock). There are three ways to solve this problem:\n\n - define classes as `open`: the big drawback is that classes are open also in production code\n - use [mock-maker](http://hadihariri.com/2016/10/04/Mocking-Kotlin-With-Mockito/) or mockito-inline dependency and [dexopener](https://github.com/tmurakami/dexopener):\n a demo is available in [RealWorldAppKotlin](https://github.com/fabioCollini/DaggerMock/tree/master/RealWorldAppKotlin) module\n - use [kotlin-allopen](https://kotlinlang.org/docs/reference/compiler-plugins.html#all-open-compiler-plugin):\n a demo is available in [RealWorldAppKotlinAllOpen](https://github.com/fabioCollini/DaggerMock/tree/master/RealWorldAppKotlinAllOpen) module\n\n## JitPack configuration\n\nDaggerMock is available on [JitPack](https://jitpack.io/#fabioCollini/DaggerMock/),\nadd the JitPack repository in your build.gradle (in top level dir):\n```gradle\nrepositories {\n    jcenter()\n    maven { url \"https://jitpack.io\" }\n}\n```\nand the dependency in the build.gradle of the module:\n\n```gradle\ndependencies {\n    testImplementation 'com.github.fabioCollini.daggermock:daggermock:0.8.5'\n    //and/or\n    androidTestImplementation 'com.github.fabioCollini.daggermock:daggermock:0.8.5'\n    \n    //kotlin helper methods\n    testImplementation 'com.github.fabioCollini.daggermock:daggermock-kotlin:0.8.5'\n    //and/or\n    androidTestImplementation 'com.github.fabioCollini.daggermock:daggermock-kotlin:0.8.5'\n}\n```\n\n## License\n\n    Copyright 2016-2017 Fabio Collini\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","funding_links":[],"categories":["Java","测试"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FfabioCollini%2FDaggerMock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FfabioCollini%2FDaggerMock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FfabioCollini%2FDaggerMock/lists"}