From cc6cb73d9f206ae8cce6b45471b634363632bf21 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Wed, 18 Mar 2026 22:01:34 +0100 Subject: [PATCH] Add regression tests for openMocks removal when @ExtendWith is added Adds tests confirming that the Mockito1to3Migration and JUnit4to5Migration recipe chains correctly remove MockitoAnnotations.openMocks(this) when @ExtendWith(MockitoExtension.class) is added to a test class. Covers the scenario from moderneinc/customer-requests#2030 where having both @ExtendWith(MockitoExtension.class) and MockitoAnnotations.openMocks(this) causes double mock instantiation. Tests verify: - Simple openMocks() call in @BeforeEach is removed - openMocks() with AutoCloseable field and close() in @AfterEach is removed - JUnit 4 to 5 migration path with openMocks() works end-to-end --- .../JunitMockitoUpgradeIntegrationTest.java | 64 +++++++++++ .../mockito/Mockito1to3MigrationTest.java | 103 ++++++++++++++++++ 2 files changed, 167 insertions(+) diff --git a/src/test/java/org/openrewrite/java/testing/mockito/JunitMockitoUpgradeIntegrationTest.java b/src/test/java/org/openrewrite/java/testing/mockito/JunitMockitoUpgradeIntegrationTest.java index 69fd31ecc..96fd54d36 100755 --- a/src/test/java/org/openrewrite/java/testing/mockito/JunitMockitoUpgradeIntegrationTest.java +++ b/src/test/java/org/openrewrite/java/testing/mockito/JunitMockitoUpgradeIntegrationTest.java @@ -118,6 +118,70 @@ public void usingAnnotationBasedMock() { ); } + @Test + void removeOpenMocksWhenExtensionAddedDuringJUnit4to5Migration() { + //language=java + rewriteRun( + spec -> spec + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "mockito-core", "junit-4", "hamcrest-3", "junit-jupiter-api-5")), + java( + """ + package org.openrewrite.java.testing.junit5; + + import org.junit.Before; + import org.junit.Test; + import org.mockito.Mock; + import org.mockito.MockitoAnnotations; + + import java.util.List; + + import static org.mockito.Mockito.verify; + + public class MockitoTests { + @Mock + List mockedList; + + @Before + public void initMocks() { + MockitoAnnotations.openMocks(this); + } + + @Test + public void usingAnnotationBasedMock() { + mockedList.add("one"); + verify(mockedList).add("one"); + } + } + """, + """ + package org.openrewrite.java.testing.junit5; + + import org.junit.jupiter.api.Test; + import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.Mock; + import org.mockito.junit.jupiter.MockitoExtension; + + import java.util.List; + + import static org.mockito.Mockito.verify; + + @ExtendWith(MockitoExtension.class) + public class MockitoTests { + @Mock + List mockedList; + + @Test + public void usingAnnotationBasedMock() { + mockedList.add("one"); + verify(mockedList).add("one"); + } + } + """ + ) + ); + } + /** * Mockito 1 used Matchers.anyVararg() to match the arguments to a variadic function. * Mockito 2+ uses Matchers.any() to match anything including the arguments to a variadic function. diff --git a/src/test/java/org/openrewrite/java/testing/mockito/Mockito1to3MigrationTest.java b/src/test/java/org/openrewrite/java/testing/mockito/Mockito1to3MigrationTest.java index 460c8b550..9215218da 100644 --- a/src/test/java/org/openrewrite/java/testing/mockito/Mockito1to3MigrationTest.java +++ b/src/test/java/org/openrewrite/java/testing/mockito/Mockito1to3MigrationTest.java @@ -287,6 +287,109 @@ void migratesCorrectlyWhenManagedDependency() { ); } + @Test + void removeOpenMocksWhenExtensionAdded() { + rewriteRun( + spec -> spec.parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "junit-jupiter-api", "mockito-core", "mockito-junit-jupiter")), + //language=java + java( + """ + import org.junit.jupiter.api.BeforeEach; + import org.junit.jupiter.api.Test; + import org.mockito.Mock; + import org.mockito.MockitoAnnotations; + + class MyTest { + @Mock + Object myMock; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void test() { + } + } + """, + """ + import org.junit.jupiter.api.Test; + import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.Mock; + import org.mockito.junit.jupiter.MockitoExtension; + + @ExtendWith(MockitoExtension.class) + class MyTest { + @Mock + Object myMock; + + @Test + void test() { + } + } + """ + ) + ); + } + + @Test + void removeOpenMocksWithCloseableWhenExtensionAdded() { + rewriteRun( + spec -> spec.parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "junit-jupiter-api", "mockito-core", "mockito-junit-jupiter")), + //language=java + java( + """ + import org.junit.jupiter.api.AfterEach; + import org.junit.jupiter.api.BeforeEach; + import org.junit.jupiter.api.Test; + import org.mockito.Mock; + import org.mockito.MockitoAnnotations; + + class MyTest { + private AutoCloseable mocks; + + @Mock + Object myMock; + + @BeforeEach + void setUp() { + mocks = MockitoAnnotations.openMocks(this); + } + + @AfterEach + void tearDown() throws Exception { + mocks.close(); + } + + @Test + void test() { + } + } + """, + """ + import org.junit.jupiter.api.Test; + import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.Mock; + import org.mockito.junit.jupiter.MockitoExtension; + + @ExtendWith(MockitoExtension.class) + class MyTest { + + @Mock + Object myMock; + + @Test + void test() { + } + } + """ + ) + ); + } + @Test void handlesAnyObjectFromMockitoWildCardImport() { rewriteRun(