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

Refactor Mockito.when on static (non mock) to try with resource #601

Merged
merged 18 commits into from
Sep 21, 2024

Conversation

Laurens-W
Copy link
Contributor

@Laurens-W Laurens-W commented Sep 12, 2024

What's your motivation?

Mockito.when on static (non mock) is no longer allowed with Mockito 4

Anything in particular you'd like reviewers to focus on?

Anyone you would like to review specifically?

@timtebeek

Checklist

  • I've added unit tests to cover both positive and negative cases
  • I've read and applied the recipe conventions and best practices
  • I've used the IntelliJ IDEA auto-formatter on affected files

@timtebeek
Copy link
Contributor

I'm seeing failures with

java.lang.IllegalStateException: LST contains missing or invalid type information	
Identifier->ParameterizedType->VariableDeclarations->Resource->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/A	
Identifier->FieldAccess->MethodInvocation->NamedVariable->VariableDeclarations->Resource->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/A	
Identifier->MethodInvocation->MethodInvocation->Block->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/mockA	
MemberReference->MethodInvocation->MethodInvocation->Block->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(MemberReference type is missing or malformed)~~>*//*~~(Identifier type is missing or malformed)~~>*/A::getA	
Identifier->MemberReference->MethodInvocation->MethodInvocation->Block->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/A	
Identifier->MethodInvocation->Block->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/aMock	

Would you already want me to have a look? Or are you still exploring those?

@timtebeek timtebeek added the enhancement New feature or request label Sep 12, 2024
@timtebeek
Copy link
Contributor

Also: could you hook this recipe into the Mockito migration already? That way we can't forget that step.

Comment on lines 63 to 67
String template = String.format("try(MockedStatic<%s> mock%s = mockStatic(%s.class)){\n" +
"mock%s.when(%s::%s).thenReturn(%s);\n" +
"}", arg_fq.getClassName(), arg_fq.getClassName(), arg_fq.getClassName(), arg_fq.getClassName(), arg_fq.getClassName(), ((J.MethodInvocation) when.getArguments().get(0)).getSimpleName(), ((J.MethodInvocation) stmt).getArguments().get(0));
m = JavaTemplate.builder(template)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of String.format, can we use #{any()} in the template as much as possible, and pass the matching LST elements as arguments into the JavaTemplate.apply? That way the type attribution is already correct on those elements.

@Laurens-W
Copy link
Contributor Author

I'm seeing failures with

java.lang.IllegalStateException: LST contains missing or invalid type information	
Identifier->ParameterizedType->VariableDeclarations->Resource->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/A	
Identifier->FieldAccess->MethodInvocation->NamedVariable->VariableDeclarations->Resource->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/A	
Identifier->MethodInvocation->MethodInvocation->Block->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/mockA	
MemberReference->MethodInvocation->MethodInvocation->Block->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(MemberReference type is missing or malformed)~~>*//*~~(Identifier type is missing or malformed)~~>*/A::getA	
Identifier->MemberReference->MethodInvocation->MethodInvocation->Block->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/A	
Identifier->MethodInvocation->Block->Try->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit	
/*~~(Identifier type is missing or malformed)~~>*/aMock	

Would you already want me to have a look? Or are you still exploring those?

I'll have a look tomorrow, am aware of them :)

@timtebeek timtebeek marked this pull request as ready for review September 16, 2024 14:57
@timtebeek timtebeek marked this pull request as draft September 16, 2024 19:43
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Copy link
Contributor

@timtebeek timtebeek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed up a couple changes already, mostly to adopt ListUtils instead of the binary before/after lists that were there previously.

Also: can you point me to any resources where the non-MockStatic usage was valid with older Mockito version? I'm having a hard time finding any sources on whether this recipe would actually match any cases in practices, as it seems to have been newly introduced in 3.4.0.

Comment on lines 135 to 143
try (MockedStatic<com.foo.A> mockA = mockStatic(com.foo.A.class)) {
mockA.when(A.getNumber()).thenReturn(-1);
assertEquals(A.getNumber(), -1);

try (MockedStatic<com.foo.A> mockA2 = mockStatic(com.foo.A.class)) {
mockA2.when(A.getNumber()).thenReturn(-2);
assertEquals(A.getNumber(), -2);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is the exact snippet we ought to be generating, but I do think we should account for more than one static mocked method.

@Laurens-W Laurens-W marked this pull request as ready for review September 19, 2024 15:12
Copy link
Contributor

@timtebeek timtebeek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Managed to get the types shortened and added some meaningful names to the extracted method and arguments to drive home what we're after there. Thanks again for the work done here! Let's hope this helps.

@timtebeek timtebeek merged commit 4367149 into main Sep 21, 2024
2 checks passed
@timtebeek timtebeek deleted the mockito-when-on-static branch September 21, 2024 11:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

2 participants