Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuntimeException: Error invoking setter with parameter class Module on object DaggerComponentBuilder #92

Open
SammyOdenhoven opened this issue Jan 9, 2019 · 5 comments

Comments

@SammyOdenhoven
Copy link

Hi there,

First off, thank you very much for your library and great work.

I've been trying to set up DaggerMock in our project, but I'm running into some problems.
Our ApplicationComponent:

@Singleton
@Component(modules = {ApplicationModule.class, NetworkModule.class, ApiKeyModule.class, InAppPurchaseModule.class})
public interface ApplicationComponent {

	//region Created for testing purposes
	TestComponent plus(TestComponent.TestModule module);
	//endregion

	ManageSubscriptionActivityComponent plus(ManageSubscriptionActivityComponent.ManageSubscriptionActivityModule module);

}

ManageSubscriptionComponent & -Module:

@PerScreen
@Subcomponent(modules = [(ManageSubscriptionActivityComponent.ManageSubscriptionActivityModule::class)])
interface ManageSubscriptionActivityComponent : BaseActivityComponent<ManageSubscriptionActivity> {

    @Module
    class ManageSubscriptionActivityModule internal constructor(
            activity: ManageSubscriptionActivity
    ) : BaseActivityModule<ManageSubscriptionActivity>(activity) {
        @Provides
        @PerScreen
        fun activityCheckout(activity: Activity, billing: Billing): ActivityCheckout {
            return Checkout.forActivity(activity, billing)
        }
        @Provides
        @PerScreen
        fun provideGetSubscriptionPriceInteractor(subscriptionManager: SubscriptionManager): GetSubscriptionPriceInteractor {
            return GetSubscriptionPriceInteractor(subscriptionManager)
        }
    }
}

Test:

class ManageSubscriptionsPresenterTest : BasePresenterIntegrationTest() {

    private val mockView = mock<ManageSubscriptionView>()

    val mockGetSubscriptionPriceInteractor: GetSubscriptionPriceInteractor = mock()

    @InjectFromComponent(TestPresenterProvider::class) lateinit var presenter: ManageSubscriptionPresenter
    @InjectFromComponent(TestPresenterProvider::class) lateinit var oauthTokenStore: OAuthTokenStore

    private val context = ApplicationProvider.getApplicationContext<Context>()
    
    @Test
    fun `setup with T3 scenario should show trial will renew`() {
        // GIVEN

        // WHEN
        presenter.attachView(mockView)

        // THEN
        inOrder(mockView).apply {
            verify(mockView, times(1)).showLoadingState()
            verify(mockView, times(1)).showContentState()
        }
    }
}

with DaggerMockRule:

class RobolectricDaggerMockTestRule : DaggerMockRule<ApplicationComponent>(
        ApplicationComponent::class.java,
        createTestApplicationModule(app),
        NetworkModule(),
        ManageSubscriptionActivityComponent.ManageSubscriptionActivityModule(activity)
) {

    companion object {
        private val app: App
            get() = ApplicationProvider.getApplicationContext()

        private val activity: ManageSubscriptionActivity
            get() = mock()
    }

    init {
        set { component -> component.inject(app) }
    }
}

When running this test, I get the following error:
java.lang.RuntimeException: Error invoking setter with parameter class com.rubicoin.invest.ui.managesubscription.ManageSubscriptionActivityComponent$ManageSubscriptionActivityModule on object com.rubicoin.invest.injection.component.DaggerApplicationComponent$Builder@5bde6148

Thank you in advance for your help!

@fabioCollini
Copy link
Owner

Hi, can you paste the whole exception?
It seems ok but it's hard to debug without the code or the full exception, maybe there is something interesting in the wrapped exception

@SammyOdenhoven
Copy link
Author

Hi there,

Please find the full exception below:

java.lang.RuntimeException: Error invoking setter with parameter class com.rubicoin.invest.ui.managesubscription.ManageSubscriptionActivityComponent$ManageSubscriptionActivityModule on object com.rubicoin.invest.injection.component.DaggerApplicationComponent$Builder@2ceb68a1

	at it.cosenonjaviste.daggermock.ObjectWrapper.invokeBuilderSetter(ObjectWrapper.java:175)
	at it.cosenonjaviste.daggermock.DaggerMockRule.initComponent(DaggerMockRule.java:238)
	at it.cosenonjaviste.daggermock.DaggerMockRule.setupComponent(DaggerMockRule.java:130)
	at it.cosenonjaviste.daggermock.DaggerMockRule.access$000(DaggerMockRule.java:36)
	at it.cosenonjaviste.daggermock.DaggerMockRule$1.evaluate(DaggerMockRule.java:110)
	at com.rubicoin.invest.androidx.integration.base.utils.MockWebServerRule$apply$1.evaluate(MockWebServerRule.kt:27)
	at com.rubicoin.invest.androidx.integration.base.utils.InvestInitializationRule$apply$1.evaluate(InvestInitializationRule.kt:15)
	at io.github.plastix.rxschedulerrule.RxSchedulerRule$3.evaluate(RxSchedulerRule.java:48)
	at com.rubicoin.invest.old.RxJava2SchedulerRule$apply$1.evaluate(RxJava2SchedulerRule.kt:38)
	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
	at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:260)
	at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:130)
	at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:42)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:84)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: java.lang.NoSuchMethodException: com.rubicoin.invest.injection.component.DaggerApplicationComponent$Builder.baseActivityModule(com.rubicoin.invest.injection.module.BaseActivityModule)
	at java.lang.Class.getMethod(Class.java:1786)
	at it.cosenonjaviste.daggermock.ObjectWrapper.getSetterMethod(ObjectWrapper.java:185)
	at it.cosenonjaviste.daggermock.ObjectWrapper.invokeBuilderSetter(ObjectWrapper.java:171)
	... 30 more

@fabioCollini
Copy link
Owner

The real error seems the last one, can you try to add the method ApplicationComponent$Builder.baseActivityModule(com.rubicoin.invest.injection.module.BaseActivityModule)? Even if you don't use it in the production code it's needed by DaggerMock to work.

@SammyOdenhoven
Copy link
Author

Hi, thanks for your reply. I changed parts of our project to now use builders, but I'm still getting the same error. I'm probably not completely sure I understand your suggested code; where should I place this?

In my ApplicationComponent I now have:

@Singleton
@Component(modules = {ApplicationModule.class, NetworkModule.class, ApiKeyModule.class, InAppPurchaseModule.class})
public interface ApplicationComponent {
	TestComponent plus(TestComponent.TestModule module);

	BaseActivityComponent.Builder baseActivityComponentBuilder();
}

and

@PerScreen
@Subcomponent(modules = [(BaseActivityModule::class)])
interface BaseActivityComponent : BaseActivityInterface<BaseActivity> {

    @Subcomponent.Builder
    interface Builder {
        fun module(module: BaseActivityModule): Builder

        fun build(): BaseActivityComponent
    }
}

Thanks again for your help.

@fabioCollini
Copy link
Owner

I think you should add a builder for ApplicationComponent as well and then add the method baseActivityModule(com.rubicoin.invest.injection.module.BaseActivityModule) there

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants