diff --git a/build.gradle.kts b/build.gradle.kts index 42276ebba..e7ccd9904 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,6 +20,7 @@ recipeDependencies { parserClasspath("org.mockito:mockito-all:1.10.19") parserClasspath("org.mockito:mockito-core:3.+") parserClasspath("org.jmockit:jmockit:1.49") + parserClasspath("org.jmockit:jmockit:1.22") // last version with NonStrictExpectations parserClasspath("org.mockito:mockito-junit-jupiter:3.+") parserClasspath("org.powermock:powermock-api-mockito:1.7.+") parserClasspath("org.powermock:powermock-core:1.7.+") diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockRewriter.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockRewriter.java index 147bcdd50..0e9829b4d 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockRewriter.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockRewriter.java @@ -29,11 +29,15 @@ import java.util.ArrayList; import java.util.List; +import static org.openrewrite.java.testing.jmockit.JMockitBlockType.NonStrictExpectations; import static org.openrewrite.java.testing.jmockit.JMockitBlockType.Verifications; class JMockitBlockRewriter { private static final String WHEN_TEMPLATE_PREFIX = "when(#{any()})."; + private static final String VERIFY_TEMPLATE_PREFIX = "verify(#{any()}"; + private static final String LENIENT_TEMPLATE_PREFIX = "lenient()."; + private static final String RETURN_TEMPLATE_PREFIX = "thenReturn("; private static final String THROW_TEMPLATE_PREFIX = "thenThrow("; private static final String LITERAL_TEMPLATE_FIELD = "#{}"; @@ -131,6 +135,11 @@ private void rewriteMethodInvocation(List statementsToRewrite) { rewriteResult(invocation, mockInvocationResults.getResults()); } + if (blockType == NonStrictExpectations) { + // no verify for NonStrictExpectations + return; + } + boolean hasTimes = false; if (mockInvocationResults.getTimes() != null) { hasTimes = true; @@ -145,7 +154,7 @@ private void rewriteMethodInvocation(List statementsToRewrite) { rewriteVerify(invocation, mockInvocationResults.getMaxTimes(), "atMost"); } if (!hasResults && !hasTimes) { - rewriteVerify(invocation, null, null); + rewriteVerify(invocation, null, ""); } } @@ -153,14 +162,11 @@ private void removeBlock() { methodBody = JavaTemplate.builder("") .javaParser(JavaParser.fromJavaVersion()) .build() - .apply( - new Cursor(visitor.getCursor(), methodBody), - nextStatementCoordinates - ); + .apply(new Cursor(visitor.getCursor(), methodBody), nextStatementCoordinates); if (bodyStatementIndex == 0) { nextStatementCoordinates = methodBody.getCoordinates().firstStatement(); } else { - setNextCoordinatesAfterLastStatementAdded(0); + setNextStatementCoordinates(0); } } @@ -171,17 +177,26 @@ private void rewriteResult(J.MethodInvocation invocation, List resul rewriteFailed = true; return; } - visitor.maybeAddImport(MOCKITO_IMPORT_FQN_PREFX, "when"); List templateParams = new ArrayList<>(); templateParams.add(invocation); templateParams.addAll(results); - - methodBody = rewriteTemplate(template, templateParams, nextStatementCoordinates); - setNextCoordinatesAfterLastStatementAdded(++numStatementsAdded); + this.rewriteFailed = !rewriteTemplate(template, templateParams, nextStatementCoordinates); + if (!this.rewriteFailed) { + this.rewriteFailed = true; + setNextStatementCoordinates(++numStatementsAdded); + // do this last making sure rewrite worked and specify hasReference=false because framework cannot find static + // reference for when method invocation when lenient is added. + boolean hasReferencesForWhen = true; + if (this.blockType == NonStrictExpectations) { + visitor.maybeAddImport(MOCKITO_IMPORT_FQN_PREFX, "lenient"); + hasReferencesForWhen = false; + } + visitor.maybeAddImport(MOCKITO_IMPORT_FQN_PREFX, "when", hasReferencesForWhen); + } } - private void rewriteVerify(J.MethodInvocation invocation, @Nullable Expression times, @Nullable String verificationMode) { + private void rewriteVerify(J.MethodInvocation invocation, @Nullable Expression times, String verificationMode) { if (invocation.getSelect() == null) { // cannot write a verification statement for an invocation without a select field return; @@ -194,7 +209,6 @@ private void rewriteVerify(J.MethodInvocation invocation, @Nullable Expression t } templateParams.add(invocation.getName().getSimpleName()); String verifyTemplate = getVerifyTemplate(invocation.getArguments(), verificationMode, templateParams); - JavaCoordinates verifyCoordinates; if (this.blockType == Verifications) { // for Verifications, replace the Verifications block @@ -203,21 +217,22 @@ private void rewriteVerify(J.MethodInvocation invocation, @Nullable Expression t // for Expectations put the verify at the end of the method verifyCoordinates = methodBody.getCoordinates().lastStatement(); } + this.rewriteFailed = !rewriteTemplate(verifyTemplate, templateParams, verifyCoordinates); + if (!this.rewriteFailed) { + if (this.blockType == Verifications) { + setNextStatementCoordinates(++numStatementsAdded); // for Expectations, verify statements added to end of method + } - methodBody = rewriteTemplate(verifyTemplate, templateParams, verifyCoordinates); - if (this.blockType == Verifications) { - setNextCoordinatesAfterLastStatementAdded(++numStatementsAdded); - } - - // do this last making sure rewrite worked and specify hasReference=false because in verify case it cannot find - // the static reference in AddImport class, and getSelect() returns not null - visitor.maybeAddImport(MOCKITO_IMPORT_FQN_PREFX, "verify", false); - if (verificationMode != null) { - visitor.maybeAddImport(MOCKITO_IMPORT_FQN_PREFX, verificationMode); + // do this last making sure rewrite worked and specify hasReference=false because in verify case framework + // cannot find the static reference + visitor.maybeAddImport(MOCKITO_IMPORT_FQN_PREFX, "verify", false); + if (!verificationMode.isEmpty()) { + visitor.maybeAddImport(MOCKITO_IMPORT_FQN_PREFX, verificationMode); + } } } - private void setNextCoordinatesAfterLastStatementAdded(int numStatementsAdded) { + private void setNextStatementCoordinates(int numStatementsAdded) { // the next statement coordinates are directly after the most recently written statement, calculated by // subtracting the removed jmockit block int nextStatementIdx = bodyStatementIndex + numStatementsAdded - 1; @@ -228,23 +243,28 @@ private void setNextCoordinatesAfterLastStatementAdded(int numStatementsAdded) { } } - private J.Block rewriteTemplate(String verifyTemplate, List templateParams, JavaCoordinates + private boolean rewriteTemplate(String template, List templateParams, JavaCoordinates rewriteCoords) { - JavaTemplate.Builder builder = JavaTemplate.builder(verifyTemplate) + int numStatementsBefore = methodBody.getStatements().size(); + methodBody = JavaTemplate.builder(template) .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "mockito-core-3.12")) - .staticImports("org.mockito.Mockito.*"); - return builder + .staticImports("org.mockito.Mockito.*") .build() .apply( new Cursor(visitor.getCursor(), methodBody), rewriteCoords, templateParams.toArray() ); + return methodBody.getStatements().size() > numStatementsBefore; } - private static @Nullable String getWhenTemplate(List results) { + private @Nullable String getWhenTemplate(List results) { boolean buildingResults = false; - final StringBuilder templateBuilder = new StringBuilder(WHEN_TEMPLATE_PREFIX); + StringBuilder templateBuilder = new StringBuilder(); + if (this.blockType == NonStrictExpectations) { + templateBuilder.append(LENIENT_TEMPLATE_PREFIX); + } + templateBuilder.append(WHEN_TEMPLATE_PREFIX); for (Expression result : results) { JavaType resultType = result.getType(); if (result instanceof J.Literal) { @@ -284,10 +304,9 @@ private static void appendToTemplate(StringBuilder templateBuilder, boolean buil templateBuilder.append(templateField); } - private static String getVerifyTemplate(List arguments, @Nullable String - verificationMode, List templateParams) { - StringBuilder templateBuilder = new StringBuilder("verify(#{any()}"); // eg verify(object - if (verificationMode != null) { + private static String getVerifyTemplate(List arguments, String verificationMode, List templateParams) { + StringBuilder templateBuilder = new StringBuilder(VERIFY_TEMPLATE_PREFIX); // eg verify(object + if (!verificationMode.isEmpty()) { templateBuilder.append(", ").append(verificationMode).append("(#{any(int)})"); // eg verify(object, times(2) } templateBuilder.append(").#{}("); // eg verify(object, times(2)).method( diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockToMockito.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockToMockito.java index 4283eedf5..04db84952 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockToMockito.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockToMockito.java @@ -29,26 +29,28 @@ import java.util.List; import java.util.Optional; +import static org.openrewrite.java.testing.jmockit.JMockitBlockType.*; + @Value @EqualsAndHashCode(callSuper = false) public class JMockitBlockToMockito extends Recipe { @Override public String getDisplayName() { - return "Rewrite JMockit Expectations and Verifications"; + return "Rewrite JMockit Expectations, Verifications and NonStrictExpectations"; } @Override public String getDescription() { - return "Rewrites JMockit `Expectations and Verifications` blocks to Mockito statements."; + return "Rewrites JMockit `Expectations, Verifications and NonStrictExpectations` blocks to Mockito statements."; } @Override public TreeVisitor getVisitor() { return Preconditions.check(Preconditions.or( - new UsesType<>(JMockitBlockType.Expectations.getFqn(), false), - new UsesType<>(JMockitBlockType.Verifications.getFqn(), false) - ), new RewriteJMockitBlockVisitor()); + new UsesType<>(Expectations.getFqn(), false), + new UsesType<>(Verifications.getFqn(), false), + new UsesType<>(NonStrictExpectations.getFqn(), false)), new RewriteJMockitBlockVisitor()); } private static class RewriteJMockitBlockVisitor extends JavaIsoVisitor { diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockType.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockType.java index e649448a0..b36c9240f 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockType.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitBlockType.java @@ -16,14 +16,17 @@ package org.openrewrite.java.testing.jmockit; import lombok.Getter; -import lombok.RequiredArgsConstructor; -@RequiredArgsConstructor @Getter enum JMockitBlockType { - Expectations("mockit.Expectations"), - Verifications("mockit.Verifications"); // Add NonStrictExpectations later + Expectations, + Verifications, + NonStrictExpectations; private final String fqn; + + JMockitBlockType() { + this.fqn = "mockit." + this.name(); + } } diff --git a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitUtils.java b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitUtils.java index a11b5246b..9d144039f 100644 --- a/src/main/java/org/openrewrite/java/testing/jmockit/JMockitUtils.java +++ b/src/main/java/org/openrewrite/java/testing/jmockit/JMockitUtils.java @@ -40,10 +40,9 @@ static Optional getJMockitBlock(Statement s) { return empty(); } - for (JMockitBlockType blockType : JMockitBlockType.values()) { - if (TypeUtils.isAssignableTo(blockType.getFqn(), clazz.getType())) { - return Optional.of(blockType); - } + JMockitBlockType blockType = JMockitBlockType.valueOf(clazz.getSimpleName()); + if (blockType != null && TypeUtils.isOfClassType(clazz.getType(), blockType.getFqn())) { + return Optional.of(blockType); } return empty(); } diff --git a/src/main/resources/META-INF/rewrite/classpath/jmockit-1.22.jar b/src/main/resources/META-INF/rewrite/classpath/jmockit-1.22.jar new file mode 100644 index 000000000..9b3cc6718 Binary files /dev/null and b/src/main/resources/META-INF/rewrite/classpath/jmockit-1.22.jar differ diff --git a/src/main/resources/META-INF/rewrite/jmockit.yml b/src/main/resources/META-INF/rewrite/jmockit.yml index 4178ebcd4..a15136715 100644 --- a/src/main/resources/META-INF/rewrite/jmockit.yml +++ b/src/main/resources/META-INF/rewrite/jmockit.yml @@ -36,6 +36,9 @@ recipeList: - org.openrewrite.java.ChangeType: oldFullyQualifiedTypeName: mockit.integration.junit5.JMockitExtension newFullyQualifiedTypeName: org.mockito.junit.jupiter.MockitoExtension + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: mockit.integration.junit4.JMockit + newFullyQualifiedTypeName: org.mockito.junit.MockitoJUnitRunner - org.openrewrite.java.dependencies.AddDependency: groupId: org.mockito artifactId: mockito-core diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoTest.java index 54d26e64c..fc03f7aef 100644 --- a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoTest.java +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitExpectationsToMockitoTest.java @@ -17,29 +17,17 @@ import org.junit.jupiter.api.Test; import org.openrewrite.DocumentExample; -import org.openrewrite.InMemoryExecutionContext; -import org.openrewrite.java.JavaParser; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; import static org.openrewrite.java.Assertions.java; +import static org.openrewrite.java.testing.jmockit.JMockitTestUtils.setDefaultParserSettings; class JMockitExpectationsToMockitoTest implements RewriteTest { + @Override public void defaults(RecipeSpec spec) { - spec - .parser(JavaParser.fromJavaVersion() - .logCompilationWarningsAndErrors(true) - .classpathFromResources(new InMemoryExecutionContext(), - "junit-jupiter-api-5.9", - "jmockit-1.49", - "mockito-core-3.12", - "mockito-junit-jupiter-3.12" - )) - .recipeFromResource( - "/META-INF/rewrite/jmockit.yml", - "org.openrewrite.java.testing.jmockit.JMockitToMockito" - ); + setDefaultParserSettings(spec); } @DocumentExample diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitNonStrictExpectationsToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitNonStrictExpectationsToMockitoTest.java new file mode 100644 index 000000000..6abe677a7 --- /dev/null +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitNonStrictExpectationsToMockitoTest.java @@ -0,0 +1,1086 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.jmockit; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; +import static org.openrewrite.java.testing.jmockit.JMockitTestUtils.MOCKITO_CORE_DEPENDENCY; +import static org.openrewrite.java.testing.jmockit.JMockitTestUtils.setParserSettings; + +class JMockitNonStrictExpectationsToMockitoTest implements RewriteTest { + + private static final String JUNIT_4_DEPENDENCY = "junit-4.13.2"; + private static final String LEGACY_JMOCKIT_DEPENDENCY = "jmockit-1.22"; + + @Override + public void defaults(RecipeSpec spec) { + setParserSettings(spec, JUNIT_4_DEPENDENCY, LEGACY_JMOCKIT_DEPENDENCY, MOCKITO_CORE_DEPENDENCY); + } + + @Test + void whenNullResult() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeField() { + return "X"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertNull; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new NonStrictExpectations() {{ + myObject.getSomeField(); + result = null; + }}; + assertNull(myObject.getSomeField()); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertNull; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + lenient().when(myObject.getSomeField()).thenReturn(null); + assertNull(myObject.getSomeField()); + } + } + """ + ) + ); + } + + @Test + void whenIntResult() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public int getSomeField() { + return 0; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new NonStrictExpectations() {{ + myObject.getSomeField(); + result = 10; + }}; + assertEquals(10, myObject.getSomeField()); + new NonStrictExpectations() {{ + myObject.getSomeField(); + this.result = 100; + }}; + assertEquals(100, myObject.getSomeField()); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + lenient().when(myObject.getSomeField()).thenReturn(10); + assertEquals(10, myObject.getSomeField()); + lenient().when(myObject.getSomeField()).thenReturn(100); + assertEquals(100, myObject.getSomeField()); + } + } + """ + ) + ); + } + + @Test + void whenStringResult() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeField(String s) { + return "X"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new NonStrictExpectations() {{ + myObject.getSomeField(anyString); + result = "foo"; + }}; + assertEquals("foo", myObject.getSomeField("bar")); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.mockito.Mockito.*; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + lenient().when(myObject.getSomeField(anyString())).thenReturn("foo"); + assertEquals("foo", myObject.getSomeField("bar")); + } + } + """ + ) + ); + } + + @Test + void whenVariableResult() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeField() { + return "X"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + String expected = "expected"; + + void test() { + new NonStrictExpectations() {{ + myObject.getSomeField(); + result = expected; + }}; + assertEquals(expected, myObject.getSomeField()); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + String expected = "expected"; + + void test() { + lenient().when(myObject.getSomeField()).thenReturn(expected); + assertEquals(expected, myObject.getSomeField()); + } + } + """ + ) + ); + } + + @Test + void whenNewClassResult() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public Object getSomeField() { + return null; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertNotNull; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new NonStrictExpectations() {{ + myObject.getSomeField(); + result = new Object(); + }}; + assertNotNull(myObject.getSomeField()); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertNotNull; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + lenient().when(myObject.getSomeField()).thenReturn(new Object()); + assertNotNull(myObject.getSomeField()); + } + } + """ + ) + ); + } + + @Test + void whenExceptionResult() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeField() { + return "X"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() throws RuntimeException { + new NonStrictExpectations() {{ + myObject.getSomeField(); + result = new RuntimeException(); + }}; + myObject.getSomeField(); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() throws RuntimeException { + lenient().when(myObject.getSomeField()).thenThrow(new RuntimeException()); + myObject.getSomeField(); + } + } + """ + ) + ); + } + + @Test + void whenReturns() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeField() { + return "X"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() throws RuntimeException { + new NonStrictExpectations() {{ + myObject.getSomeField(); + returns("foo", "bar"); + }}; + assertEquals("foo", myObject.getSomeField()); + assertEquals("bar", myObject.getSomeField()); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() throws RuntimeException { + lenient().when(myObject.getSomeField()).thenReturn("foo", "bar"); + assertEquals("foo", myObject.getSomeField()); + assertEquals("bar", myObject.getSomeField()); + } + } + """ + ) + ); + } + + @Test + void whenClassArgumentMatcher() { + //language=java + rewriteRun( + java( + """ + import java.util.List; + + class MyObject { + public String getSomeField(List input) { + return "X"; + } + public String getSomeOtherField(Object input) { + return "Y"; + } + } + """ + ), + java( + """ + import java.util.ArrayList; + import java.util.List; + + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertNull; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new NonStrictExpectations() {{ + myObject.getSomeField((List) any); + result = null; + myObject.getSomeOtherField((Object) any); + result = null; + }}; + assertNull(myObject.getSomeField(new ArrayList<>())); + assertNull(myObject.getSomeOtherField(new Object())); + } + } + """, + """ + import java.util.ArrayList; + import java.util.List; + + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertNull; + import static org.mockito.Mockito.*; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + lenient().when(myObject.getSomeField(anyList())).thenReturn(null); + lenient().when(myObject.getSomeOtherField(any(Object.class))).thenReturn(null); + assertNull(myObject.getSomeField(new ArrayList<>())); + assertNull(myObject.getSomeOtherField(new Object())); + } + } + """ + ) + ); + } + + @Test + void whenNoArguments() { + //language=java + rewriteRun( + java( + """ + import java.util.List; + + class MyObject { + public String getSomeField() { + return "X"; + } + } + """ + ), + java( + """ + import java.util.ArrayList; + import java.util.List; + + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertNull; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new NonStrictExpectations() {{ + myObject.getSomeField(); + result = null; + }}; + assertNull(myObject.getSomeField()); + } + } + """, + """ + import java.util.ArrayList; + import java.util.List; + + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertNull; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + lenient().when(myObject.getSomeField()).thenReturn(null); + assertNull(myObject.getSomeField()); + } + } + """ + ) + ); + } + + @DocumentExample + @Test + void whenMixedArgumentMatcher() { + //language=java + rewriteRun( + java( + """ + import java.util.List; + + class MyObject { + public String getSomeField(String s, String s2, String s3, long l1) { + return "X"; + } + } + """ + ), + java( + """ + import java.util.ArrayList; + import java.util.List; + + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertNull; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + String bazz = "bazz"; + new NonStrictExpectations() {{ + myObject.getSomeField("foo", anyString, bazz, 10L); + result = null; + }}; + assertNull(myObject.getSomeField("foo", "bar", bazz, 10L)); + } + } + """, + """ + import java.util.ArrayList; + import java.util.List; + + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertNull; + import static org.mockito.Mockito.*; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + String bazz = "bazz"; + lenient().when(myObject.getSomeField(eq("foo"), anyString(), eq(bazz), eq(10L))).thenReturn(null); + assertNull(myObject.getSomeField("foo", "bar", bazz, 10L)); + } + } + """ + ) + ); + } + + @Test + void whenSetupStatements() { + //language=java + rewriteRun( + java( + """ + class MyObject { + + public String getSomeField(String s) { + return "X"; + } + public String getString() { + return "Y"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + String a = "a"; + String s = "s"; + + new NonStrictExpectations() {{ + myObject.getSomeField(anyString); + result = s; + + myObject.getString(); + result = a; + }}; + + assertEquals("s", myObject.getSomeField("foo")); + assertEquals("a", myObject.getString()); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.mockito.Mockito.*; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + String a = "a"; + String s = "s"; + lenient().when(myObject.getSomeField(anyString())).thenReturn(s); + lenient().when(myObject.getString()).thenReturn(a); + + assertEquals("s", myObject.getSomeField("foo")); + assertEquals("a", myObject.getString()); + } + } + """ + ) + ); + } + + @Test + void whenSetupStatements2() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeField(String s) { + return "X"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + String a = "a"; + new NonStrictExpectations() {{ + myObject.getSomeField(anyString); + String s = "s"; + String b = "b"; + result = s; + }}; + + assertEquals("s", myObject.getSomeField("foo")); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.mockito.Mockito.*; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + String a = "a"; + String s = "s"; + String b = "b"; + lenient().when(myObject.getSomeField(anyString())).thenReturn(s); + + assertEquals("s", myObject.getSomeField("foo")); + } + } + """ + ) + ); + } + + @Test + void whenSpy() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeField() { + return "X"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Tested; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + + @RunWith(JMockit.class) + class MyTest { + @Tested + MyObject myObject; + + void test() { + new NonStrictExpectations(myObject) {{ + myObject.getSomeField(); + result = "foo"; + }}; + assertEquals("foo", myObject.getSomeField()); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.InjectMocks; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @InjectMocks + MyObject myObject; + + void test() { + lenient().when(myObject.getSomeField()).thenReturn("foo"); + assertEquals("foo", myObject.getSomeField()); + } + } + """ + ) + ); + } + + @Test + void whenMultipleStatements() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeStringField(String input, long otherInput) { + return "X"; + } + public int getSomeIntField() { + return 0; + } + public Object getSomeObjectField() { + return new Object(); + } + public void doSomething() {} + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertNull; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + Object myObject; + + @Mocked + MyObject myOtherObject; + + void test() { + new NonStrictExpectations() {{ + myObject.hashCode(); + result = 10; + myOtherObject.getSomeObjectField(); + result = null; + myObject.wait(anyLong, anyInt); + myOtherObject.getSomeStringField(anyString, anyLong); + result = "foo"; + }}; + assertEquals(10, myObject.hashCode()); + assertNull(myOtherObject.getSomeObjectField()); + myObject.wait(10L, 10); + assertEquals("foo", myOtherObject.getSomeStringField("bar", 10L)); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertNull; + import static org.mockito.Mockito.*; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + Object myObject; + + @Mock + MyObject myOtherObject; + + void test() { + lenient().when(myObject.hashCode()).thenReturn(10); + lenient().when(myOtherObject.getSomeObjectField()).thenReturn(null); + lenient().when(myOtherObject.getSomeStringField(anyString(), anyLong())).thenReturn("foo"); + assertEquals(10, myObject.hashCode()); + assertNull(myOtherObject.getSomeObjectField()); + myObject.wait(10L, 10); + assertEquals("foo", myOtherObject.getSomeStringField("bar", 10L)); + } + } + """ + ) + ); + } + + @Test + void whenMultipleExpectations() { + //language=java + rewriteRun( + java( + """ + class MyObject { + public String getSomeStringField() { + return "X"; + } + } + """ + ), + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertNull; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + MyObject myObject; + + void test() { + new NonStrictExpectations() {{ + myObject.getSomeStringField(); + result = "a"; + }}; + assertEquals("a", myObject.getSomeStringField()); + new NonStrictExpectations() {{ + myObject.getSomeStringField(); + result = "b"; + }}; + assertEquals("b", myObject.getSomeStringField()); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertNull; + import static org.mockito.Mockito.lenient; + import static org.mockito.Mockito.when; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + MyObject myObject; + + void test() { + lenient().when(myObject.getSomeStringField()).thenReturn("a"); + assertEquals("a", myObject.getSomeStringField()); + lenient().when(myObject.getSomeStringField()).thenReturn("b"); + assertEquals("b", myObject.getSomeStringField()); + } + } + """ + ) + ); + } + + @Test + void whenNoResultsNoTimes() { + //language=java + rewriteRun( + java( + """ + import mockit.NonStrictExpectations; + import mockit.Mocked; + import mockit.integration.junit4.JMockit; + import org.junit.runner.RunWith; + + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertNull; + + @RunWith(JMockit.class) + class MyTest { + @Mocked + Object myObject; + + void test() { + new NonStrictExpectations() {{ + myObject.wait(anyLong); + }}; + myObject.wait(1L); + } + } + """, + """ + import org.junit.runner.RunWith; + import org.mockito.Mock; + import org.mockito.junit.MockitoJUnitRunner; + + import static org.junit.Assert.assertEquals; + import static org.junit.Assert.assertNull; + + @RunWith(MockitoJUnitRunner.class) + class MyTest { + @Mock + Object myObject; + + void test() { + myObject.wait(1L); + } + } + """ + ) + ); + } +} diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitTestUtils.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitTestUtils.java new file mode 100644 index 000000000..0b21832ab --- /dev/null +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitTestUtils.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.testing.jmockit; + +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; + +public class JMockitTestUtils { + + static final String MOCKITO_CORE_DEPENDENCY = "mockito-core-3.12"; + static final String JUNIT_5_JUPITER_DEPENDENCY = "junit-jupiter-api-5.9"; + static final String JMOCKIT_DEPENDENCY = "jmockit-1.49"; + static final String MOCKITO_JUPITER_DEPENDENCY = "mockito-junit-jupiter-3.12"; + + static void setDefaultParserSettings(RecipeSpec spec) { + setParserSettings(spec, JUNIT_5_JUPITER_DEPENDENCY, + JMOCKIT_DEPENDENCY, + MOCKITO_CORE_DEPENDENCY, + MOCKITO_JUPITER_DEPENDENCY); + } + + static void setParserSettings(RecipeSpec spec, String... javaParserTestDependencies) { + spec.parser(JavaParser.fromJavaVersion() + .logCompilationWarningsAndErrors(true) + .classpathFromResources(new InMemoryExecutionContext(), + javaParserTestDependencies + )) + .recipeFromResource( + "/META-INF/rewrite/jmockit.yml", + "org.openrewrite.java.testing.jmockit.JMockitToMockito" + ); + } +} diff --git a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitVerificationsToMockitoTest.java b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitVerificationsToMockitoTest.java index 23022dcb5..faaff8edb 100644 --- a/src/test/java/org/openrewrite/java/testing/jmockit/JMockitVerificationsToMockitoTest.java +++ b/src/test/java/org/openrewrite/java/testing/jmockit/JMockitVerificationsToMockitoTest.java @@ -17,30 +17,17 @@ import org.junit.jupiter.api.Test; import org.openrewrite.DocumentExample; -import org.openrewrite.InMemoryExecutionContext; -import org.openrewrite.java.JavaParser; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; import org.openrewrite.test.TypeValidation; import static org.openrewrite.java.Assertions.java; +import static org.openrewrite.java.testing.jmockit.JMockitTestUtils.setDefaultParserSettings; class JMockitVerificationsToMockitoTest implements RewriteTest { @Override public void defaults(RecipeSpec spec) { - spec - .parser(JavaParser.fromJavaVersion() - .logCompilationWarningsAndErrors(true) - .classpathFromResources(new InMemoryExecutionContext(), - "junit-jupiter-api-5.9", - "jmockit-1.49", - "mockito-core-3.12", - "mockito-junit-jupiter-3.12" - )) - .recipeFromResource( - "/META-INF/rewrite/jmockit.yml", - "org.openrewrite.java.testing.jmockit.JMockitToMockito" - ); + setDefaultParserSettings(spec); } @DocumentExample