From 69675f29f24fe7dafb3f2e57e3b8c3aa14c4bce2 Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sat, 28 Oct 2023 16:46:48 -0700 Subject: [PATCH 01/13] JMockit to Mockito Recipe - handle void methods --- .../JMockitExpectationsToMockitoWhen.java | 35 +++++---- .../testing/jmockit/JMockitToMockitoTest.java | 72 +++++++++++++++++-- 2 files changed, 90 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java index f830ecc6d..33cca9849 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java @@ -58,6 +58,7 @@ public TreeVisitor getVisitor() { private static class RewriteExpectationsVisitor extends JavaIsoVisitor { + private static final String VOID_RESULT_TEMPLATE = "doNothing().when(#{any(java.lang.String)});"; private static final String PRIMITIVE_RESULT_TEMPLATE = "when(#{any()}).thenReturn(#{});"; private static final String OBJECT_RESULT_TEMPLATE = "when(#{any()}).thenReturn(#{any(java.lang.String)});"; private static final String EXCEPTION_RESULT_TEMPLATE = "when(#{any()}).thenThrow(#{any()});"; @@ -80,8 +81,8 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl List statements = md.getBody().getStatements(); // iterate over each statement in the method body, find Expectations blocks and rewrite them - for (int i = 0; i < statements.size(); i++) { - Statement s = statements.get(i); + for (int bodyStatementIndex = 0; bodyStatementIndex < statements.size(); bodyStatementIndex++) { + Statement s = statements.get(bodyStatementIndex); if (!(s instanceof J.NewClass)) { continue; } @@ -99,28 +100,26 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl assert nc.getBody().getStatements().size() == 1 : "Expectations block is malformed"; // we have a valid Expectations block, update imports and rewrite with Mockito statements - maybeAddImport("org.mockito.Mockito", "when"); maybeRemoveImport("mockit.Expectations"); - // the first coordinates are the coordinates the Expectations block, replacing it + // the first coordinates are the coordinates of the Expectations block, replacing it coordinates = nc.getCoordinates().replace(); J.Block expectationsBlock = (J.Block) nc.getBody().getStatements().get(0); - List expectationStatements = expectationsBlock.getStatements(); List templateParams = new ArrayList<>(); // iterate over the expectations statements and rebuild the method body - for (Statement expectationStatement : expectationStatements) { - // TODO: handle void methods (including final statement) - + int mockitoStatementIndex = 0; + for (Statement expectationStatement : expectationsBlock.getStatements()) { // TODO: handle additional jmockit expectations features if (expectationStatement instanceof J.MethodInvocation) { if (!templateParams.isEmpty()) { // apply template to build new method body - newBody = buildNewBody(ctx, templateParams, i); + newBody = buildNewBody(ctx, templateParams, bodyStatementIndex + mockitoStatementIndex); // reset template params for next expectation templateParams = new ArrayList<>(); + mockitoStatementIndex += 1; } templateParams.add(expectationStatement); } else { @@ -131,7 +130,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl // handle the last statement if (!templateParams.isEmpty()) { - newBody = buildNewBody(ctx, templateParams, i); + newBody = buildNewBody(ctx, templateParams, bodyStatementIndex + mockitoStatementIndex); } } @@ -139,12 +138,21 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl } private J.Block buildNewBody(ExecutionContext ctx, List templateParams, int newStatementIndex) { - Expression result = (Expression) templateParams.get(1); + Expression result = null; + String staticImport; + if (templateParams.size() > 1) { + maybeAddImport("org.mockito.Mockito", "when"); + staticImport = "org.mockito.Mockito.when"; + result = (Expression) templateParams.get(1); + } else { + maybeAddImport("org.mockito.Mockito", "doNothing"); + staticImport = "org.mockito.Mockito.doNothing"; + } String template = getTemplate(result); J.Block newBody = JavaTemplate.builder(template) .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) - .staticImports("org.mockito.Mockito.when") + .staticImports(staticImport) .build() .apply( new Cursor(getCursor(), cursorLocation), @@ -173,6 +181,9 @@ private J.Block buildNewBody(ExecutionContext ctx, List templateParams, * Based on the result type, we need to use a different template. */ private static String getTemplate(Expression result) { + if (result == null) { + return VOID_RESULT_TEMPLATE; + } String template; JavaType resultType = Objects.requireNonNull(result.getType()); if (resultType instanceof JavaType.Primitive) { diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java index b8658ec10..dac3e1540 100644 --- a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java @@ -42,6 +42,62 @@ public void defaults(RecipeSpec spec) { ); } + @Test + void jMockitExpectationsToMockitoVoidResult() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public void doSomething() {} + } + """ + ), + java( + """ + import mockit.Expectations; + import mockit.Mocked; + import mockit.integration.junit5.JMockitExtension; + import org.junit.jupiter.api.extension.ExtendWith; + + import static org.junit.jupiter.api.Assertions.assertNull; + + @ExtendWith(JMockitExtension.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new Expectations() {{ + myObject.doSomething(); + }}; + myObject.doSomething(); + } + } + """, + """ + import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.Mock; + import org.mockito.junit.jupiter.MockitoExtension; + + import static org.junit.jupiter.api.Assertions.assertNull; + import static org.mockito.Mockito.doNothing; + + @ExtendWith(MockitoExtension.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + doNothing().when(myObject.doSomething()); + myObject.doSomething(); + } + } + """ + ) + ); + } + @Test void jMockitExpectationsToMockitoWhenNullResult() { //language=java @@ -57,12 +113,12 @@ public String getSomeField() { ), java( """ - import static org.junit.jupiter.api.Assertions.assertNull; - import mockit.Expectations; import mockit.Mocked; import mockit.integration.junit5.JMockitExtension; import org.junit.jupiter.api.extension.ExtendWith; + + import static org.junit.jupiter.api.Assertions.assertNull; @ExtendWith(JMockitExtension.class) class MyTest { @@ -79,12 +135,12 @@ void test() { } """, """ - import static org.junit.jupiter.api.Assertions.assertNull; - import static org.mockito.Mockito.when; - import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; + + import static org.junit.jupiter.api.Assertions.assertNull; + import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class MyTest { @@ -351,6 +407,7 @@ public int getSomeField() { public Object getSomeObjectField() { return new Object(); } + public void doSomething() {} } """ ), @@ -378,9 +435,11 @@ void test() { result = 10; myOtherObject.getSomeObjectField(); result = null; + myObject.doSomething(); }}; assertEquals(10, myObject.getSomeField()); assertNull(myOtherObject.getSomeObjectField()); + myObject.doSomething(); } } """, @@ -391,6 +450,7 @@ void test() { import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; + import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -404,8 +464,10 @@ class MyTest { void test() { when(myObject.getSomeField()).thenReturn(10); when(myOtherObject.getSomeObjectField()).thenReturn(null); + doNothing().when(myObject.doSomething()); assertEquals(10, myObject.getSomeField()); assertNull(myOtherObject.getSomeObjectField()); + myObject.doSomething(); } } """ From e282852778c993b1618c7cfb35671d26209d4b2d Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sat, 28 Oct 2023 17:01:52 -0700 Subject: [PATCH 02/13] polish --- .../java/testing/jmockit/JMockitExpectationsToMockitoWhen.java | 2 +- .../openrewrite/java/testing/jmockit/JMockitToMockitoTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java index 33cca9849..dfaa70ce1 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java @@ -62,7 +62,7 @@ private static class RewriteExpectationsVisitor extends JavaIsoVisitor Date: Sun, 29 Oct 2023 13:56:23 -0700 Subject: [PATCH 03/13] polish and rename --- ...java => JMockitExpectationsToMockito.java} | 19 +++++-------------- .../resources/META-INF/rewrite/jmockit.yml | 2 +- 2 files changed, 6 insertions(+), 15 deletions(-) rename src/main/java/org/openrewrite/java/testing/jmockit/{JMockitExpectationsToMockitoWhen.java => JMockitExpectationsToMockito.java} (91%) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java similarity index 91% rename from src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java rename to src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index dfaa70ce1..af0bd7d0e 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoWhen.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -39,7 +39,7 @@ @Value @EqualsAndHashCode(callSuper = false) -public class JMockitExpectationsToMockitoWhen extends Recipe { +public class JMockitExpectationsToMockito extends Recipe { @Override public String getDisplayName() { return "Rewrite JMockit Expectations"; @@ -47,12 +47,12 @@ public String getDisplayName() { @Override public String getDescription() { - return "Rewrites JMockit `Expectations` to `Mockito.when`."; + return "Rewrites JMockit `Expectations` blocks to Mockito statements."; } @Override public TreeVisitor getVisitor() { - return Preconditions.check(new UsesType<>("mockit.*", false), + return Preconditions.check(new UsesType<>("mockit.Expectations", false), new RewriteExpectationsVisitor()); } @@ -149,7 +149,6 @@ private J.Block buildNewBody(ExecutionContext ctx, List templateParams, staticImport = "org.mockito.Mockito.doNothing"; } String template = getTemplate(result); - J.Block newBody = JavaTemplate.builder(template) .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) .staticImports(staticImport) @@ -160,16 +159,8 @@ private J.Block buildNewBody(ExecutionContext ctx, List templateParams, templateParams.toArray() ); - List newStatements = new ArrayList<>(newBody.getStatements().size()); - for (int i = 0; i < newBody.getStatements().size(); i++) { - Statement s = newBody.getStatements().get(i); - if (i == newStatementIndex) { - // next statement coordinates are immediately after the statement just added - coordinates = s.getCoordinates().after(); - } - newStatements.add(s); - } - newBody = newBody.withStatements(newStatements); + // next statement coordinates are immediately after the statement just added + coordinates = newBody.getStatements().get(newStatementIndex).getCoordinates().after(); // cursor location is now the new body cursorLocation = newBody; diff --git a/src/main/resources/META-INF/rewrite/jmockit.yml b/src/main/resources/META-INF/rewrite/jmockit.yml index ffbc6b8c6..9b308784c 100644 --- a/src/main/resources/META-INF/rewrite/jmockit.yml +++ b/src/main/resources/META-INF/rewrite/jmockit.yml @@ -28,7 +28,7 @@ recipeList: - org.openrewrite.java.ChangeType: oldFullyQualifiedTypeName: mockit.integration.junit5.JMockitExtension newFullyQualifiedTypeName: org.mockito.junit.jupiter.MockitoExtension - - org.openrewrite.java.testing.jmockit.JMockitExpectationsToMockitoWhen + - org.openrewrite.java.testing.jmockit.JMockitExpectationsToMockito - org.openrewrite.java.dependencies.AddDependency: groupId: org.mockito artifactId: mockito-core From 140cd9b1913aa4ac7939e7c8b3a28fdbee2ef00f Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sun, 29 Oct 2023 14:14:47 -0700 Subject: [PATCH 04/13] polish --- .../jmockit/JMockitExpectationsToMockito.java | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index af0bd7d0e..275a33db0 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -61,14 +61,9 @@ private static class RewriteExpectationsVisitor extends JavaIsoVisitor statements = md.getBody().getStatements(); @@ -103,7 +99,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl maybeRemoveImport("mockit.Expectations"); // the first coordinates are the coordinates of the Expectations block, replacing it - coordinates = nc.getCoordinates().replace(); + JavaCoordinates coordinates = nc.getCoordinates().replace(); J.Block expectationsBlock = (J.Block) nc.getBody().getStatements().get(0); List templateParams = new ArrayList<>(); @@ -115,7 +111,14 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl if (expectationStatement instanceof J.MethodInvocation) { if (!templateParams.isEmpty()) { // apply template to build new method body - newBody = buildNewBody(ctx, templateParams, bodyStatementIndex + mockitoStatementIndex); + newBody = buildNewBody(ctx, templateParams, cursorLocation, coordinates); + + // next statement coordinates are immediately after the statement just added + int newStatementIndex = bodyStatementIndex + mockitoStatementIndex; + coordinates = newBody.getStatements().get(newStatementIndex).getCoordinates().after(); + + // cursor location is now the new body + cursorLocation = newBody; // reset template params for next expectation templateParams = new ArrayList<>(); @@ -130,14 +133,14 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl // handle the last statement if (!templateParams.isEmpty()) { - newBody = buildNewBody(ctx, templateParams, bodyStatementIndex + mockitoStatementIndex); + newBody = buildNewBody(ctx, templateParams, cursorLocation, coordinates); } } return md.withBody(newBody); } - private J.Block buildNewBody(ExecutionContext ctx, List templateParams, int newStatementIndex) { + private J.Block buildNewBody(ExecutionContext ctx, List templateParams, Object cursorLocation, JavaCoordinates coordinates) { Expression result = null; String staticImport; if (templateParams.size() > 1) { @@ -148,8 +151,7 @@ private J.Block buildNewBody(ExecutionContext ctx, List templateParams, maybeAddImport("org.mockito.Mockito", "doNothing"); staticImport = "org.mockito.Mockito.doNothing"; } - String template = getTemplate(result); - J.Block newBody = JavaTemplate.builder(template) + return JavaTemplate.builder(getTemplate(result)) .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) .staticImports(staticImport) .build() @@ -158,14 +160,6 @@ private J.Block buildNewBody(ExecutionContext ctx, List templateParams, coordinates, templateParams.toArray() ); - - // next statement coordinates are immediately after the statement just added - coordinates = newBody.getStatements().get(newStatementIndex).getCoordinates().after(); - - // cursor location is now the new body - cursorLocation = newBody; - - return newBody; } /* @@ -186,7 +180,7 @@ private static String getTemplate(Expression result) { } catch (ClassNotFoundException e) { throw new RuntimeException(e); } - template = Throwable.class.isAssignableFrom(resultClass) ? EXCEPTION_RESULT_TEMPLATE : OBJECT_RESULT_TEMPLATE; + template = Throwable.class.isAssignableFrom(resultClass) ? THROWABLE_RESULT_TEMPLATE : OBJECT_RESULT_TEMPLATE; } else { throw new IllegalStateException("Unexpected value: " + result.getType()); } From 6d604d5c138c1ea1f6adfb789aa14c80d1a24562 Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sun, 29 Oct 2023 18:48:33 -0700 Subject: [PATCH 05/13] polish --- .../java/testing/jmockit/JMockitExpectationsToMockito.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index 275a33db0..c4511eef4 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -111,7 +111,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl if (expectationStatement instanceof J.MethodInvocation) { if (!templateParams.isEmpty()) { // apply template to build new method body - newBody = buildNewBody(ctx, templateParams, cursorLocation, coordinates); + newBody = applyTemplate(ctx, templateParams, cursorLocation, coordinates); // next statement coordinates are immediately after the statement just added int newStatementIndex = bodyStatementIndex + mockitoStatementIndex; @@ -133,14 +133,14 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl // handle the last statement if (!templateParams.isEmpty()) { - newBody = buildNewBody(ctx, templateParams, cursorLocation, coordinates); + newBody = applyTemplate(ctx, templateParams, cursorLocation, coordinates); } } return md.withBody(newBody); } - private J.Block buildNewBody(ExecutionContext ctx, List templateParams, Object cursorLocation, JavaCoordinates coordinates) { + private J.Block applyTemplate(ExecutionContext ctx, List templateParams, Object cursorLocation, JavaCoordinates coordinates) { Expression result = null; String staticImport; if (templateParams.size() > 1) { From 960fa250af40b30d256ac9e33a3e1f15b2956aca Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sun, 29 Oct 2023 20:40:00 -0700 Subject: [PATCH 06/13] Handle argument matchers --- .../jmockit/JMockitExpectationsToMockito.java | 49 ++++++++++- .../testing/jmockit/JMockitToMockitoTest.java | 81 +++++++++++++++++-- 2 files changed, 119 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index c4511eef4..031584bc0 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -15,9 +15,7 @@ */ package org.openrewrite.java.testing.jmockit; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.regex.Pattern; import lombok.EqualsAndHashCode; @@ -63,7 +61,19 @@ private static class RewriteExpectationsVisitor extends JavaIsoVisitor JMOCKIT_ARGUMENT_MATCHERS = new HashSet<>(); + static { + JMOCKIT_ARGUMENT_MATCHERS.add("anyString"); + JMOCKIT_ARGUMENT_MATCHERS.add("anyInt"); + JMOCKIT_ARGUMENT_MATCHERS.add("anyLong"); + JMOCKIT_ARGUMENT_MATCHERS.add("anyDouble"); + JMOCKIT_ARGUMENT_MATCHERS.add("anyFloat"); + JMOCKIT_ARGUMENT_MATCHERS.add("anyBoolean"); + JMOCKIT_ARGUMENT_MATCHERS.add("anyByte"); + JMOCKIT_ARGUMENT_MATCHERS.add("anyChar"); + JMOCKIT_ARGUMENT_MATCHERS.add("anyShort"); + JMOCKIT_ARGUMENT_MATCHERS.add("any"); + } @Override public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDeclaration, ExecutionContext ctx) { @@ -151,6 +161,7 @@ private J.Block applyTemplate(ExecutionContext ctx, List templateParams, maybeAddImport("org.mockito.Mockito", "doNothing"); staticImport = "org.mockito.Mockito.doNothing"; } + rewriteArgumentMatchers(ctx, templateParams); return JavaTemplate.builder(getTemplate(result)) .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) .staticImports(staticImport) @@ -162,6 +173,36 @@ private J.Block applyTemplate(ExecutionContext ctx, List templateParams, ); } + private void rewriteArgumentMatchers(ExecutionContext ctx, List templateParams) { + J.MethodInvocation invocation = (J.MethodInvocation) templateParams.get(0); + List newArguments = new ArrayList<>(invocation.getArguments().size()); + for (Expression methodArgument : invocation.getArguments()) { + if (!isArgumentMatcher(methodArgument)) { + newArguments.add(methodArgument); + continue; + } + String argumentMatcher = ((J.Identifier) methodArgument).getSimpleName(); + maybeAddImport("org.mockito.Mockito", argumentMatcher); + newArguments.add(JavaTemplate.builder(argumentMatcher + "()") + .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) + .staticImports("org.mockito.Mockito." + argumentMatcher) + .build() + .apply( + new Cursor(getCursor(), methodArgument), + methodArgument.getCoordinates().replace() + )); + } + templateParams.set(0, invocation.withArguments(newArguments)); + } + + private static boolean isArgumentMatcher(Expression expression) { + if (!(expression instanceof J.Identifier)) { + return false; + } + J.Identifier identifier = (J.Identifier) expression; + return JMOCKIT_ARGUMENT_MATCHERS.contains(identifier.getSimpleName()); + } + /* * Based on the result type, we need to use a different template. */ diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java index 21478159b..8e8e10f11 100644 --- a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java @@ -216,6 +216,66 @@ void test() { ); } + @Test + void jMockitExpectationsToMockitoWhenStringResult() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeField(String s) { + return "X"; + } + } + """ + ), + java( + """ + import mockit.Expectations; + import mockit.Mocked; + import mockit.integration.junit5.JMockitExtension; + import org.junit.jupiter.api.extension.ExtendWith; + + import static org.junit.jupiter.api.Assertions.assertEquals; + + @ExtendWith(JMockitExtension.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new Expectations() {{ + myObject.getSomeField(anyString); + result = "foo"; + }}; + assertEquals("foo", myObject.getSomeField("bar")); + } + } + """, + """ + import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.Mock; + import org.mockito.junit.jupiter.MockitoExtension; + + import static org.junit.jupiter.api.Assertions.assertEquals; + import static org.mockito.Mockito.anyString; + import static org.mockito.Mockito.when; + + @ExtendWith(MockitoExtension.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + when(myObject.getSomeField(anyString())).thenReturn("foo"); + assertEquals("foo", myObject.getSomeField("bar")); + } + } + """ + ) + ); + } + @Test void jMockitExpectationsToMockitoWhenVariableResult() { //language=java @@ -401,7 +461,10 @@ void jMockitExpectationsToMockitoWhenMultipleStatements() { java( """ class MyObject { - public int getSomeField() { + public String getSomeStringField(String input, String otherInput) { + return "X"; + } + public int getSomeIntField() { return 0; } public Object getSomeObjectField() { @@ -431,15 +494,18 @@ class MyTest { void test() { new Expectations() {{ - myObject.getSomeField(); + myObject.getSomeIntField(); result = 10; myOtherObject.getSomeObjectField(); result = null; myObject.doSomething(); + myOtherObject.getSomeStringField(anyString, anyString); + result = "foo"; }}; - assertEquals(10, myObject.getSomeField()); + assertEquals(10, myObject.getSomeIntField()); assertNull(myOtherObject.getSomeObjectField()); myObject.doSomething(); + assertEquals("foo", myOtherObject.getSomeStringField("bar", "bazz")); } } """, @@ -450,8 +516,7 @@ void test() { import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; - import static org.mockito.Mockito.doNothing; - import static org.mockito.Mockito.when; + import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class MyTest { @@ -462,12 +527,14 @@ class MyTest { MyObject myOtherObject; void test() { - when(myObject.getSomeField()).thenReturn(10); + when(myObject.getSomeIntField()).thenReturn(10); when(myOtherObject.getSomeObjectField()).thenReturn(null); doNothing().when(myObject.doSomething()); - assertEquals(10, myObject.getSomeField()); + when(myOtherObject.getSomeStringField(anyString(), anyString())).thenReturn("foo"); + assertEquals(10, myObject.getSomeIntField()); assertNull(myOtherObject.getSomeObjectField()); myObject.doSomething(); + assertEquals("foo", myOtherObject.getSomeStringField("bar", "bazz")); } } """ From 22450a13c9eb5eeecd260c56cf33c058455c23ce Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sun, 29 Oct 2023 20:57:57 -0700 Subject: [PATCH 07/13] polish --- .../testing/jmockit/JMockitExpectationsToMockito.java | 7 ++----- .../java/testing/jmockit/JMockitToMockitoTest.java | 10 +++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index 031584bc0..505e15e23 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -162,7 +162,7 @@ private J.Block applyTemplate(ExecutionContext ctx, List templateParams, staticImport = "org.mockito.Mockito.doNothing"; } rewriteArgumentMatchers(ctx, templateParams); - return JavaTemplate.builder(getTemplate(result)) + return JavaTemplate.builder(getMockitoStatementTemplate(result)) .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) .staticImports(staticImport) .build() @@ -203,10 +203,7 @@ private static boolean isArgumentMatcher(Expression expression) { return JMOCKIT_ARGUMENT_MATCHERS.contains(identifier.getSimpleName()); } - /* - * Based on the result type, we need to use a different template. - */ - private static String getTemplate(Expression result) { + private static String getMockitoStatementTemplate(Expression result) { if (result == null) { return VOID_RESULT_TEMPLATE; } diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java index 8e8e10f11..1debde1ac 100644 --- a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java @@ -461,7 +461,7 @@ void jMockitExpectationsToMockitoWhenMultipleStatements() { java( """ class MyObject { - public String getSomeStringField(String input, String otherInput) { + public String getSomeStringField(String input, long otherInput) { return "X"; } public int getSomeIntField() { @@ -499,13 +499,13 @@ void test() { myOtherObject.getSomeObjectField(); result = null; myObject.doSomething(); - myOtherObject.getSomeStringField(anyString, anyString); + myOtherObject.getSomeStringField(anyString, anyLong); result = "foo"; }}; assertEquals(10, myObject.getSomeIntField()); assertNull(myOtherObject.getSomeObjectField()); myObject.doSomething(); - assertEquals("foo", myOtherObject.getSomeStringField("bar", "bazz")); + assertEquals("foo", myOtherObject.getSomeStringField("bar", 10L)); } } """, @@ -530,11 +530,11 @@ void test() { when(myObject.getSomeIntField()).thenReturn(10); when(myOtherObject.getSomeObjectField()).thenReturn(null); doNothing().when(myObject.doSomething()); - when(myOtherObject.getSomeStringField(anyString(), anyString())).thenReturn("foo"); + when(myOtherObject.getSomeStringField(anyString(), anyLong())).thenReturn("foo"); assertEquals(10, myObject.getSomeIntField()); assertNull(myOtherObject.getSomeObjectField()); myObject.doSomething(); - assertEquals("foo", myOtherObject.getSomeStringField("bar", "bazz")); + assertEquals("foo", myOtherObject.getSomeStringField("bar", 10L)); } } """ From 13cc2da8dca3cfa1c35e4231ba402a9f3303e7bf Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sun, 29 Oct 2023 21:07:02 -0700 Subject: [PATCH 08/13] polish --- .../testing/jmockit/JMockitExpectationsToMockito.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index 505e15e23..f6ad3c46e 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -152,19 +152,16 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl private J.Block applyTemplate(ExecutionContext ctx, List templateParams, Object cursorLocation, JavaCoordinates coordinates) { Expression result = null; - String staticImport; + String methodName = "doNothing"; if (templateParams.size() > 1) { - maybeAddImport("org.mockito.Mockito", "when"); - staticImport = "org.mockito.Mockito.when"; + methodName = "when"; result = (Expression) templateParams.get(1); - } else { - maybeAddImport("org.mockito.Mockito", "doNothing"); - staticImport = "org.mockito.Mockito.doNothing"; } + maybeAddImport("org.mockito.Mockito", methodName); rewriteArgumentMatchers(ctx, templateParams); return JavaTemplate.builder(getMockitoStatementTemplate(result)) .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) - .staticImports(staticImport) + .staticImports("org.mockito.Mockito." + methodName) .build() .apply( new Cursor(getCursor(), cursorLocation), From 79ed23ea22f2e6996c864454c579ac8600582cac Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sun, 29 Oct 2023 21:44:24 -0700 Subject: [PATCH 09/13] remove reflection --- .../jmockit/JMockitExpectationsToMockito.java | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index f6ad3c46e..52653ed92 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -29,11 +29,7 @@ import org.openrewrite.java.JavaParser; import org.openrewrite.java.JavaTemplate; import org.openrewrite.java.search.UsesType; -import org.openrewrite.java.tree.Expression; -import org.openrewrite.java.tree.J; -import org.openrewrite.java.tree.JavaCoordinates; -import org.openrewrite.java.tree.JavaType; -import org.openrewrite.java.tree.Statement; +import org.openrewrite.java.tree.*; @Value @EqualsAndHashCode(callSuper = false) @@ -209,13 +205,9 @@ private static String getMockitoStatementTemplate(Expression result) { if (resultType instanceof JavaType.Primitive) { template = PRIMITIVE_RESULT_TEMPLATE; } else if (resultType instanceof JavaType.Class) { - Class resultClass; - try { - resultClass = Class.forName(((JavaType.Class) resultType).getFullyQualifiedName()); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - template = Throwable.class.isAssignableFrom(resultClass) ? THROWABLE_RESULT_TEMPLATE : OBJECT_RESULT_TEMPLATE; + template = TypeUtils.isAssignableTo(Throwable.class.getName(), resultType) + ? THROWABLE_RESULT_TEMPLATE + : OBJECT_RESULT_TEMPLATE; } else { throw new IllegalStateException("Unexpected value: " + result.getType()); } From e769377cab96c795e8252575e194bd2c06040b26 Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Sun, 29 Oct 2023 21:58:26 -0700 Subject: [PATCH 10/13] format --- .../java/testing/jmockit/JMockitExpectationsToMockito.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index 52653ed92..c92317e44 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -146,7 +146,8 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl return md.withBody(newBody); } - private J.Block applyTemplate(ExecutionContext ctx, List templateParams, Object cursorLocation, JavaCoordinates coordinates) { + private J.Block applyTemplate(ExecutionContext ctx, List templateParams, Object cursorLocation, + JavaCoordinates coordinates) { Expression result = null; String methodName = "doNothing"; if (templateParams.size() > 1) { From c56a747522793be99b84bff38a785bf91a89b69b Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Mon, 30 Oct 2023 11:09:49 -0700 Subject: [PATCH 11/13] polish --- .../java/testing/jmockit/JMockitExpectationsToMockito.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index c92317e44..70da7c8ae 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -56,7 +56,6 @@ private static class RewriteExpectationsVisitor extends JavaIsoVisitor JMOCKIT_ARGUMENT_MATCHERS = new HashSet<>(); static { JMOCKIT_ARGUMENT_MATCHERS.add("anyString"); @@ -93,7 +92,7 @@ public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration methodDecl continue; } J.Identifier clazz = (J.Identifier) nc.getClazz(); - if (clazz.getType() == null || !clazz.getType().isAssignableFrom(EXPECTATIONS_PATTERN)) { + if (!TypeUtils.isAssignableTo("mockit.Expectations", clazz.getType())) { continue; } // empty Expectations block is considered invalid From 0c28f55ae6a38474f0e6d61ce528cdf2457f465f Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Mon, 30 Oct 2023 11:25:41 -0700 Subject: [PATCH 12/13] fix package of argument matchers --- .../java/testing/jmockit/JMockitExpectationsToMockito.java | 4 ++-- .../java/testing/jmockit/JMockitToMockitoTest.java | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index 70da7c8ae..0ce0c9c59 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -175,10 +175,10 @@ private void rewriteArgumentMatchers(ExecutionContext ctx, List template continue; } String argumentMatcher = ((J.Identifier) methodArgument).getSimpleName(); - maybeAddImport("org.mockito.Mockito", argumentMatcher); + maybeAddImport("org.mockito.ArgumentMatchers", argumentMatcher); newArguments.add(JavaTemplate.builder(argumentMatcher + "()") .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) - .staticImports("org.mockito.Mockito." + argumentMatcher) + .staticImports("org.mockito.ArgumentMatchers." + argumentMatcher) .build() .apply( new Cursor(getCursor(), methodArgument), diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java index 1debde1ac..565888f26 100644 --- a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java @@ -258,7 +258,7 @@ void test() { import org.mockito.junit.jupiter.MockitoExtension; import static org.junit.jupiter.api.Assertions.assertEquals; - import static org.mockito.Mockito.anyString; + import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -516,7 +516,10 @@ void test() { import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; - import static org.mockito.Mockito.*; + import static org.mockito.ArgumentMatchers.anyLong; + import static org.mockito.ArgumentMatchers.anyString; + import static org.mockito.Mockito.doNothing; + import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class MyTest { From f97915424b9eac4cc2a42959c41bc7a4e217b6ff Mon Sep 17 00:00:00 2001 From: tinder-dthomson Date: Mon, 30 Oct 2023 11:28:14 -0700 Subject: [PATCH 13/13] Revert "fix package of argument matchers" This reverts commit 0c28f55ae6a38474f0e6d61ce528cdf2457f465f. --- .../java/testing/jmockit/JMockitExpectationsToMockito.java | 4 ++-- .../java/testing/jmockit/JMockitToMockitoTest.java | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java index 0ce0c9c59..70da7c8ae 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockito.java @@ -175,10 +175,10 @@ private void rewriteArgumentMatchers(ExecutionContext ctx, List template continue; } String argumentMatcher = ((J.Identifier) methodArgument).getSimpleName(); - maybeAddImport("org.mockito.ArgumentMatchers", argumentMatcher); + maybeAddImport("org.mockito.Mockito", argumentMatcher); newArguments.add(JavaTemplate.builder(argumentMatcher + "()") .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) - .staticImports("org.mockito.ArgumentMatchers." + argumentMatcher) + .staticImports("org.mockito.Mockito." + argumentMatcher) .build() .apply( new Cursor(getCursor(), methodArgument), diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java index 565888f26..1debde1ac 100644 --- a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitToMockitoTest.java @@ -258,7 +258,7 @@ void test() { import org.mockito.junit.jupiter.MockitoExtension; import static org.junit.jupiter.api.Assertions.assertEquals; - import static org.mockito.ArgumentMatchers.anyString; + import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -516,10 +516,7 @@ void test() { import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; - import static org.mockito.ArgumentMatchers.anyLong; - import static org.mockito.ArgumentMatchers.anyString; - import static org.mockito.Mockito.doNothing; - import static org.mockito.Mockito.when; + import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class MyTest {