SONARJAVA-6509 Implement S9024: @InjectMocks should be preferred over manual initialization#5789
SONARJAVA-6509 Implement S9024: @InjectMocks should be preferred over manual initialization#5789NoemieBenard wants to merge 9 commits into
@InjectMocks should be preferred over manual initialization#5789Conversation
Code Review ✅ Approved 1 resolved / 1 findingsImplements S9024 to enforce the use of ✅ 1 resolved✅ Edge Case: openMocks detection aborts scan on first bodiless setup method
OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
Code Review ✅ Approved 1 resolved / 1 findingsImplements S9024 to enforce ✅ 1 resolved✅ Edge Case: openMocks detection aborts scan on first bodiless setup method
OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
|
rombirli
left a comment
There was a problem hiding this comment.
Looks good to me overall: the implementation is sound and the rule itself makes sense. One thing we could still improve in a follow-up is covering more edge cases in the implementation.
There was a problem hiding this comment.
This sample is a bit narrow because every case revolves around OrderProcessor, which is an easy @InjectMocks target. It would be useful to add another constructed class with less straightforward constructors, for example one mixing mocks with non-mock/primitive parameters, to cover edge cases beyond the happy path.
| return null; | ||
| } | ||
|
|
||
| private boolean allArgsMockFields(NewClassTree newClass) { |
There was a problem hiding this comment.
This is purely argument-based and does not inspect constructor injectability. A constructor taking two parameters of the same mock type still matches here, even though @InjectMocks resolution is ambiguous/unreliable in that case.
for example :
static class SameTypeDependenciesOrderProcessor {
SameTypeDependenciesOrderProcessor(PaymentGateway primaryGateway, PaymentGateway backupGateway) {}
}| if (expression instanceof NewClassTree newClass | ||
| && isFieldAssignment(tree.variable()) | ||
| && allArgsMockFields(newClass)) { | ||
| issues.add(newClass); |
There was a problem hiding this comment.
This only checks that we are assigning a new instance to a field; it never verifies that the constructed type is actually a valid @InjectMocks target. For example, automatic @InjectMocks instantiation fails on non-static inner classes because Mockito cannot implicitly resolve the required enclosing outer instance. We could filter these out.




Summary by Gitar
MockitoInjectMocksShouldBeUsedCheck(S9024) to flag manual instantiation of test objects when@InjectMockscould be used.MockitoInjectMocksShouldBeUsedSamplecovering various JUnit 4/5 scenarios and Mockito configurations.MockitoInjectMocksShouldBeUsedCheckTestto verify the detection logic.This will update automatically on new commits.