From 18f671d02ed987610b0a7203ff89aaae8143af1c Mon Sep 17 00:00:00 2001 From: 123Haynes <209302+123Haynes@users.noreply.github.com> Date: Fri, 6 Dec 2024 16:03:01 +0100 Subject: [PATCH] Add ReplaceMockBeanAndSpyBean Recipe (#646) * Add ReplaceMockBeanAndSpyBean Recipe * Add ReplaceMockBeanAndSpyBean Recipe * Update src/test/java/org/openrewrite/java/spring/boot3/ReplaceMockBeanAndSpyBeanTest.java Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: Tim te Beek Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../rewrite/replace-mock-and-spybean.yml | 48 +++ .../boot3/ReplaceMockBeanAndSpyBeanTest.java | 312 ++++++++++++++++++ 2 files changed, 360 insertions(+) create mode 100644 src/main/resources/META-INF/rewrite/replace-mock-and-spybean.yml create mode 100644 src/test/java/org/openrewrite/java/spring/boot3/ReplaceMockBeanAndSpyBeanTest.java diff --git a/src/main/resources/META-INF/rewrite/replace-mock-and-spybean.yml b/src/main/resources/META-INF/rewrite/replace-mock-and-spybean.yml new file mode 100644 index 00000000..026c8df3 --- /dev/null +++ b/src/main/resources/META-INF/rewrite/replace-mock-and-spybean.yml @@ -0,0 +1,48 @@ +# +# 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. +# + +--- +type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.java.boot3.ReplaceMockBeanAndSpyBean +displayName: Replace `@MockBean` and `@SpyBean` +description: Replaces `@MockBean` and `@SpyBean` annotations with `@MockitoBean` and `@MockitoSpyBean`. +recipeList: + - org.openrewrite.java.ChangeAnnotationAttributeName: + annotationType: org.springframework.boot.test.mock.mockito.MockBean + oldAttributeName: answer + newAttributeName: answers + - org.openrewrite.java.RemoveAnnotationAttribute: + annotationType: org.springframework.boot.test.mock.mockito.MockBean + attributeName: classes + - org.openrewrite.java.RemoveAnnotationAttribute: + annotationType: org.springframework.boot.test.mock.mockito.MockBean + attributeName: value + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.springframework.boot.test.mock.mockito.MockBean + newFullyQualifiedTypeName: org.springframework.test.context.bean.override.mockito.MockitoBean + + - org.openrewrite.java.RemoveAnnotationAttribute: + annotationType: org.springframework.boot.test.mock.mockito.SpyBean + attributeName: classes + - org.openrewrite.java.RemoveAnnotationAttribute: + annotationType: org.springframework.boot.test.mock.mockito.SpyBean + attributeName: value + - org.openrewrite.java.RemoveAnnotationAttribute: + annotationType: org.springframework.boot.test.mock.mockito.SpyBean + attributeName: proxyTargetAware + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.springframework.boot.test.mock.mockito.SpyBean + newFullyQualifiedTypeName: org.springframework.test.context.bean.override.mockito.MockitoSpyBean diff --git a/src/test/java/org/openrewrite/java/spring/boot3/ReplaceMockBeanAndSpyBeanTest.java b/src/test/java/org/openrewrite/java/spring/boot3/ReplaceMockBeanAndSpyBeanTest.java new file mode 100644 index 00000000..afbc626a --- /dev/null +++ b/src/test/java/org/openrewrite/java/spring/boot3/ReplaceMockBeanAndSpyBeanTest.java @@ -0,0 +1,312 @@ +/* + * 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.boot3; + +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 ReplaceMockBeanAndSpyBeanTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.recipeFromResources("org.openrewrite.java.boot3.ReplaceMockBeanAndSpyBean") + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), + "spring-boot-test", "mockito-core")); + } + + @DocumentExample + @Test + void replacesMockBeanWithMockitoBean() { + rewriteRun( + // Input source file before applying the recipe + java( + """ + import org.springframework.boot.test.mock.mockito.MockBean; + + public class SomeTest { + @MockBean + private String someService; + } + """, + // Expected output after applying the recipe + """ + import org.springframework.test.context.bean.override.mockito.MockitoBean; + + public class SomeTest { + @MockitoBean + private String someService; + } + """ + ) + ); + } + + @Test + void replacesMockBeanWithMockitoBeanWithAttributes() { + rewriteRun( + // Input source file before applying the recipe + java( + """ + import org.mockito.Answers; + import org.springframework.boot.test.mock.mockito.MockBean; + + public class SomeTest { + @MockBean(name="someName", answer="Answers.RETURNS_DEFAULTS", classes=String.class, value=String.class) + private String someService; + } + """, + // Expected output after applying the recipe + """ + import org.mockito.Answers; + import org.springframework.test.context.bean.override.mockito.MockitoBean; + + public class SomeTest { + @MockitoBean(name="someName", answers="Answers.RETURNS_DEFAULTS") + private String someService; + } + """ + ) + ); + } + + @Test + void replacesMockBeanWithParamsWithMockitoBeanWithParams() { + rewriteRun( + // Input source file before applying the recipe + java( + """ + import org.springframework.boot.test.mock.mockito.MockBean; + + public class SomeTest { + @MockBean(name="bean1") + private String someService; + } + """, + // Expected output after applying the recipe + """ + import org.springframework.test.context.bean.override.mockito.MockitoBean; + + public class SomeTest { + @MockitoBean(name="bean1") + private String someService; + } + """ + ) + ); + } + + @Test + void doesNotChangeOtherAnnotations() { + rewriteRun( + java( + """ + import org.springframework.boot.test.mock.mockito.MockBean; + + public class SomeTest { + + @MockBean + @Deprecated + private String someService; + } + """, + """ + import org.springframework.test.context.bean.override.mockito.MockitoBean; + + public class SomeTest { + + @MockitoBean + @Deprecated + private String someService; + } + """ + ) + ); + } + + @Test + void handlesNoMockBeanImport() { + rewriteRun( + java( + """ + public class SomeTest { + @org.springframework.boot.test.mock.mockito.MockBean + private String someService; + } + """, + """ + public class SomeTest { + @org.springframework.test.context.bean.override.mockito.MockitoBean + private String someService; + } + """ + ) + ); + } + + @Test + void replacesMockBeanWithMockitoBeanAndSpyBeanWithMockitoSpyBean() { + rewriteRun( + // Input source file before applying the recipe + java( + """ + import org.springframework.boot.test.mock.mockito.MockBean; + import org.springframework.boot.test.mock.mockito.SpyBean; + + public class SomeTest { + @SpyBean + private String someService; + + @MockBean + private String someMockService; + } + """, + // Expected output after applying the recipe + """ + import org.springframework.test.context.bean.override.mockito.MockitoBean; + import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; + + public class SomeTest { + @MockitoSpyBean + private String someService; + + @MockitoBean + private String someMockService; + } + """ + ) + ); + } + + @Test + void replacesSpyBeanWithMockitoSpyBean() { + rewriteRun( + // Input source file before applying the recipe + java( + """ + import org.springframework.boot.test.mock.mockito.SpyBean; + + public class SomeTest { + @SpyBean + private String someService; + } + """, + // Expected output after applying the recipe + """ + import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; + + public class SomeTest { + @MockitoSpyBean + private String someService; + } + """ + ) + ); + } + + @Test + void replacesSpyBeanWithMockitoSpyBeanwithAttributes() { + rewriteRun( + // Input source file before applying the recipe + java( + """ + import org.springframework.boot.test.mock.mockito.SpyBean; + + public class SomeTest { + @SpyBean(name="someName", classes=String.class, value=String.class, proxyTargetAware=true) + private String someService; + } + """, + // Expected output after applying the recipe + """ + import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; + + public class SomeTest { + @MockitoSpyBean(name="someName") + private String someService; + } + """ + ) + ); + } + + @Test + void doesNotChangeOtherAnnotationsSpyBean() { + rewriteRun( + java( + """ + import org.springframework.boot.test.mock.mockito.SpyBean; + + public class SomeTest { + + @SpyBean + @Deprecated + private String someService; + } + """, + """ + import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; + + public class SomeTest { + + @MockitoSpyBean + @Deprecated + private String someService; + } + """ + ) + ); + } + + @Test + void handlesNoSpyBeanImport() { + rewriteRun( + java( + """ + public class SomeTest { + @org.springframework.boot.test.mock.mockito.SpyBean + private String someService; + } + """, + """ + public class SomeTest { + @org.springframework.test.context.bean.override.mockito.MockitoSpyBean + private String someService; + } + """ + ) + ); + } + + @Test + void doesNothingWhenNoAnnotationPresent() { + rewriteRun( + java( + """ + public class SomeTest { + private String someService; + } + """ + ) + ); + } +}