diff --git a/src/main/java/org/openrewrite/java/spring/test/SpringRulesToJUnitExtension.java b/src/main/java/org/openrewrite/java/spring/test/SpringRulesToJUnitExtension.java new file mode 100644 index 00000000..eff500cf --- /dev/null +++ b/src/main/java/org/openrewrite/java/spring/test/SpringRulesToJUnitExtension.java @@ -0,0 +1,94 @@ +/* + * Copyright 2024 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.spring.test;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Preconditions;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.AnnotationMatcher;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.JavaParser;
+import org.openrewrite.java.JavaTemplate;
+import org.openrewrite.java.search.UsesType;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.TypeUtils;
+
+import static java.util.Comparator.comparing;
+
+public class SpringRulesToJUnitExtension extends Recipe {
+
+ private static final String SPRING_CLASS_RULE = "org.springframework.test.context.junit4.rules.SpringClassRule";
+ private static final String SPRING_METHOD_RULE = "org.springframework.test.context.junit4.rules.SpringMethodRule";
+ private static final String EXTEND_WITH = "org.junit.jupiter.api.extension.ExtendWith";
+ private static final String SPRING_EXTENSION = "org.springframework.test.context.junit.jupiter.SpringExtension";
+ private static final AnnotationMatcher ANNOTATION_MATCHER = new AnnotationMatcher(String.format("@%s(%s.class)", EXTEND_WITH, SPRING_EXTENSION), true);
+
+
+ @Override
+ public String getDisplayName() {
+ return "Replace `SpringClassRule` and `SpringMethodRule` with JUnit 5 `SpringExtension`";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Replace JUnit 4's `SpringClassRule` and `SpringMethodRule` with JUnit 5's `SpringExtension` or rely on an existing `@SpringBootTest`.";
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return Preconditions.check(
+ Preconditions.or(
+ new UsesType<>(SPRING_CLASS_RULE, true),
+ new UsesType<>(SPRING_METHOD_RULE, true)
+ ),
+ new JavaIsoVisitor
+ * 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.
+ */
+@NonNullApi @NonNullFields
+package org.openrewrite.java.spring.test;
+
+import org.openrewrite.internal.lang.NonNullApi;
+import org.openrewrite.internal.lang.NonNullFields;
diff --git a/src/main/resources/META-INF/rewrite/spring-boot-24.yml b/src/main/resources/META-INF/rewrite/spring-boot-24.yml
index e5576bc9..7eaff941 100644
--- a/src/main/resources/META-INF/rewrite/spring-boot-24.yml
+++ b/src/main/resources/META-INF/rewrite/spring-boot-24.yml
@@ -116,6 +116,7 @@ recipeList:
- org.openrewrite.java.spring.boot2.UnnecessarySpringExtension
- org.openrewrite.java.spring.boot2.ReplaceExtendWithAndContextConfiguration
- org.openrewrite.java.spring.boot2.RemoveObsoleteSpringRunners
+ - org.openrewrite.java.spring.test.SpringRulesToJUnitExtension
- org.openrewrite.java.dependencies.AddDependency:
groupId: org.springframework.boot
artifactId: spring-boot-tools
diff --git a/src/test/java/org/openrewrite/java/spring/test/SpringRulesToJUnitExtensionTest.java b/src/test/java/org/openrewrite/java/spring/test/SpringRulesToJUnitExtensionTest.java
new file mode 100644
index 00000000..294b50ec
--- /dev/null
+++ b/src/test/java/org/openrewrite/java/spring/test/SpringRulesToJUnitExtensionTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2024 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.spring.test;
+
+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;
+
+class SpringRulesToJUnitExtensionTest implements RewriteTest {
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipe(new SpringRulesToJUnitExtension())
+ .parser(JavaParser.fromJavaVersion()
+ .classpathFromResources(new InMemoryExecutionContext(), "spring-boot-test", "spring-test")
+ .dependsOn("package org.junit; public @interface ClassRule {}", "package org.junit; public @interface Rule {}")
+ );
+ }
+
+ @Test
+ @DocumentExample
+ void migrateWithSpringBootTestPresent() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import org.springframework.boot.test.context.SpringBootTest;
+ import org.springframework.test.context.junit4.rules.SpringClassRule;
+ import org.springframework.test.context.junit4.rules.SpringMethodRule;
+ import org.junit.ClassRule;
+ import org.junit.Rule;
+
+ @SpringBootTest
+ class SomeTest {
+
+ @ClassRule
+ public static final SpringClassRule springClassRule = new SpringClassRule();
+
+ @Rule
+ public final SpringMethodRule springMethodRule = new SpringMethodRule();
+
+ }
+ """,
+ """
+ import org.springframework.boot.test.context.SpringBootTest;
+
+ @SpringBootTest
+ class SomeTest {
+
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void migrateSingleAnnotation() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import org.springframework.boot.test.context.SpringBootTest;
+ import org.springframework.test.context.junit4.rules.SpringMethodRule;
+ import org.junit.Rule;
+
+ @SpringBootTest
+ class SomeTest {
+
+ @Rule
+ public final SpringMethodRule springMethodRule = new SpringMethodRule();
+
+ }
+ """,
+ """
+ import org.springframework.boot.test.context.SpringBootTest;
+
+ @SpringBootTest
+ class SomeTest {
+
+ }
+ """
+ )
+ );
+ }
+
+ @Test
+ void migrateAndAddSpringExtension() {
+ rewriteRun(
+ //language=java
+ java(
+ """
+ import org.springframework.test.context.junit4.rules.SpringClassRule;
+ import org.springframework.test.context.junit4.rules.SpringMethodRule;
+ import org.junit.ClassRule;
+ import org.junit.Rule;
+
+ class SomeTest {
+
+ @ClassRule
+ public static final SpringClassRule springClassRule = new SpringClassRule();
+
+ @Rule
+ public final SpringMethodRule springMethodRule = new SpringMethodRule();
+
+ }
+ """,
+ """
+ import org.junit.jupiter.api.extension.ExtendWith;
+ import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+ @ExtendWith(SpringExtension.class)
+ class SomeTest {
+
+ }
+ """
+ )
+ );
+ }
+}