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

Improvement: allow configuring injection and init behaviour #2971

Open
black-snow opened this issue Apr 12, 2023 · 4 comments
Open

Improvement: allow configuring injection and init behaviour #2971

black-snow opened this issue Apr 12, 2023 · 4 comments

Comments

@black-snow
Copy link

Ref.: #70 and #1935 (and maybe others)

In some cases it'd be helpful if you could tell Mockito what method should be used to construct / init objects or what mocks to inject. Also, there currently are some silent failures with @InjectMocks.

I'd like to propose two approaches to improve the situation:

(1) Add an optional argument to the @InjectMocks annotation to limit it to certain kinds of initialization.
For example @InjeckMocks(via = org.mockito.whatevs.ConstructorInjection), that will fail (loudly) on error.
Adding new parameters to constructors should then explcitly fail a test (unless you mocked the new thing before already - for some reason).

So, imagine you have:

class MyClass {
    public MyClass(final MyOtherThing1 one) {}
}

// and

class SomeTest {
    @Mock 
    MyOtherThing1 one;

    @InjectMocks
    MyClass theThing;

    @Test 
    // ...
}

Now, when you don't change (all) your test code first, you might have:

class MyClass {
    public MyClass(final MyOtherThing1 one, final MyOtherThing2 two) {}
}

and magic would happen and / or Mockito would fail silently. But with:

    @InjectMocks(via = org.mockito.whatevs.ConstructorInjection)
    MyClass theThing;

Mockito would fail explicitly for there's no MyOtherThing2 in the test class.

(2) Add an optional strategy parameter to the @InjectMocks annotation, controlling what constructor to choose in case there are multiple candidates. For example @InjectMocks(strategy = org.mockito.whatevs.strategies.LongestParamList would pick the constructor with the largest number of parameters (and some defined behaviour if there are multiple) and MatchingSignature would trying to resolve the constructor with the mocks provided in the test.

P.S.: Currently on vacation and it's hard to type this on a mobile; don't expect a draft PR in the near future ;)

@TimvdLippe
Copy link
Contributor

I am still of the opinion that for those complicated use cases, we should not enhance @InjectMocks: #1518 Instead, you should use an appropriate dependency injection framework to wire up your mocks in your tests.

@Bragolgirith
Copy link

To this purpose, can we please just deprecate @InjectMocks so people can stop using it :)

@daniel-matheis-vivavis
Copy link

I would assume that this discussion is not up-to-date and that the current plan is rather this: keep InjectMocks but make it work for the usual cases, see #3123 (comment)
please correct me if i'm wrong...

@oracle-fusion-middleware-team

The philosophy is persuasive: "Mokito is to mock, not to assemble." @TimvdLippe is correct on this.
However, after 10 years of the original post, people still encounter this.
Maybe the simplest change for mokito to help people out is to add some text in the error message of the NPE:
"Cannot invoke aaa beacause bbb is null" -> "Cannot invoke aaa beacause bbb is null. If this happens for object annotated with @Injectmocks, please check if the constructor of the class contains the very dependency, mokito support 2 kinds of injections... (you do the language)"

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

5 participants