-
Notifications
You must be signed in to change notification settings - Fork 39
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
WIP Mockito strict stubs enforcement #5
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick skim; very cool! 🎉. I'm afraid I won't have much time this week to really dive in, seeing as the "Corona project" is still in full swing. But if after these hints you're still stuck I'll find time :)
...r-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/MockitoAnnotationCheck.java
Outdated
Show resolved
Hide resolved
...r-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/MockitoAnnotationCheck.java
Outdated
Show resolved
Hide resolved
...r-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/MockitoAnnotationCheck.java
Outdated
Show resolved
Hide resolved
...r-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/MockitoAnnotationCheck.java
Outdated
Show resolved
Hide resolved
// And here I would like to say | ||
// "Please add @MockitoSettings(strictness = STRICT_STUBS)", | ||
// but don't know how =( | ||
fixBuilder.delete(violatingClass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd need to find the relevant class and add it to that. We should be able to find that by recursing down the AST. That said, I wonder whether the following approach might have worked better:
- Instead of matching on
CompilationUnitTree
, match on class declarations. - Ignore non-top-level classes.
- Then do the logic you have now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only reason I need to access it on compilation level is access to imports. Is it possible to access imports on a classTree level?
In my head this version "should work", but for some reason, it does not replace. Do you have any tips? |
8f92269
to
72c265e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mordavolt my primary tip is to run failing tests in a debugger :). Rebaed and added a commit to fix the build.
About getting the imports some other way: IIRC that's possible yes; will come back to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some comments for further improvements, and a commit with a simpler implementation :)
private static final long serialVersionUID = 1L; | ||
private static final String MOCKITO_SETTINGS = "org.mockito.junit.jupiter.MockitoSettings"; | ||
private static final String STRICT_STUBS = "org.mockito.quality.Strictness.STRICT_STUBS"; | ||
private static final String MOCKITO_ANNOTATION = "@MockitoSettings(strictness = STRICT_STUBS)"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since STRICT_STUBS
is the default, I think @MockitoSettings
would do.
private static final String STRICT_STUBS = "org.mockito.quality.Strictness.STRICT_STUBS"; | ||
private static final String MOCKITO_ANNOTATION = "@MockitoSettings(strictness = STRICT_STUBS)"; | ||
private static final Matcher<AnnotationTree> MOCKITO_ANNOTATION_MATCHER = | ||
allOf(isType(MOCKITO_SETTINGS), hasArgumentWithValue("strictness", isSameType(STRICT_STUBS))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this requires some more work/thought:
- If a class explicitly specifies another type of
strictness
we should probably respect that. - I suspect this won't match
@MockitoSettings
(no arguments), while that default enables strictness. - Not yet an issue, but once
@MockitoSettings
gets a second argument we should be prepared to merge the settings. (Or fall back to warning only.)
BugCheckerRefactoringTestHelper.newInstance(new MockitoAnnotationCheck(), getClass()); | ||
|
||
@Test | ||
public void testIdentification() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also add negative test cases: already-annotated classes, inner classes.
c6e34b6
to
2029d1a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebased. @Mordavolt are you still interested in this PR?
(@hisener @nathankooij WDYT of this proposal?)
public Description matchClass(ClassTree clazz, VisitorState state) { | ||
if (ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class) != null | ||
|| HAS_STRICT_STUBS_ANNOTATION.matches(clazz, state) | ||
|| !importsMockito(state)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should exclude non-test code, like the Mockito references under picnic-java-support-modules/test-support/src/main
. For this looking at a file's path is a bad practice; instead we could look at the class name (fast, but "meh") or check for the presence of a JUnit test method, like in #6. Currently slightly tending to the latter.
This was on my list but never find time to review it. After a very quick look, isn't
|
@hisener Yes, you are exactly correct. But we don't use the extension. So the whole purpose of this PR is to enforce using the extension, so also enforce using the strict mocks. We do it indirectly by adding
|
Does Even though I am not a big fan of |
Yes, it seems that the use of Alternatively, we could detect (in)correct usage of (I do agree that strict stubbing is a fantastic idea, though. :)) |
So two points regarding this:
Combining those two statements I've come to this solution - if a test imports mockito, then I want to enforce |
I guess it depends on the overhead. If the overhead is significant enough to offset the time lost due to build failures triggered by this check, then we should likely be selective. TBH, I don't expect that to be the case. 🤔 (Whatever we do; I still had fun reviewing the PR 😉) |
So I was operating under the impression that
With that said, I can see how enforcing |
Ouch, that'd introduce quite some (otherwise unnecessary) boilerplate 🤔 |
Just for clarification, since my description was a bit ambiguous: I mean you cannot combine field declaration and assignment (e.g. |
2029d1a
to
d039af8
Compare
To update you on this. I wanted to abandon this PR and go the "enable extension everywhere" way, but I don't think it's that simple.
And I could not figure out where to put this file. I'd like it to be in the source code, but META-INF is about the jar (right?), so I couldn't figure out how to enable the extension. Any help would be appreciated. Has anyone made JUnit autoload an extension in all test classes? |
@Mordavolt that location is the service loader path. It's the file that is auto-generated when you use the But in this case you'd have to create it manually. That can be done by placing it under (This would have to be done for every module. There is a way around that, but ask me another time :) ) |
Closing this PR in favour of https://github.com/PicnicSupermarket/picnic-wms/pull/1812. |
Attempt at enforcing
@MockitoSettings(strictness = STRICT_STUBS)
if an import fromorg.mockito
detected.This is WIP as it detects violating classes, but suggests removing them :D
Also, auto-fix is not implemented, as I am not sure if I am on the right path at all.