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

Unable to @InjectMocks on instance of android.app.Activity #3243

Open
realdadfish opened this issue Jan 23, 2024 · 1 comment
Open

Unable to @InjectMocks on instance of android.app.Activity #3243

realdadfish opened this issue Jan 23, 2024 · 1 comment

Comments

@realdadfish
Copy link
Contributor

realdadfish commented Jan 23, 2024

Given the following code

class LoginActivityTest {
    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Mock
    SomeClass someClass;

    @Mock
    SomeOtherClass someOtherClass;

    ActivityController<TestLoginActivity> loginActivityActivityController =
            Robolectric.buildActivity(TestLoginActivity.class);

    @InjectMocks
    TestLoginActivity testLoginActivity = loginActivityActivityController.get();


    @Test
    public void testSomething() {}

    public static class TestLoginActivity extends android.app.Activity {
        SomeClass someClass;
        SomeOtherClass someOtherClass;
    }
}

the injection fails with the following error:

Mockito couldn't inject mock dependency on field 'private java.lang.Object android.app.Activity.mInstanceTracker' that is annotated with @InjectMocks in your test, 
because there were multiple matching mocks (i.e. fields annotated with @Mock and having matching type): someClass.
If you have multiple fields of same type in your class under test then consider naming the @Mock fields identically to the respective class under test's fields, so Mockito can match them by name.
	at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at app//org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:588)
	at app//org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$2(SandboxTestRunner.java:290)
	at app//org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:101)
	at java.base@11.0.20.1/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base@11.0.20.1/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base@11.0.20.1/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base@11.0.20.1/java.lang.Thread.run(Thread.java:829)

Issue here is that Android's android.app.Activity has this mInstanceTracker as private variable that, because it is of type Object, matches every possible mock. I think Mockito's approach to inject things here is a little too greedy; Mockito should not scan library files for injectable fields or - since this is not really detectable - at least have some kind of package filter option / possibility to rule out foreign classes that should not be touched.

@realdadfish
Copy link
Contributor Author

This is also a regression, since this popped up for us when updating an age-old 2.x version of Mockito to the most recent 5.9.0.

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

1 participant