Skip to content

Commit d4e0b9d

Browse files
klauermtimtebeeksambsnydD067517tpoeppke
authored
Further improvements to replace powermockito method calls by mockito (#315)
* Unit Test for replacing mockStatic method. * Modified recipe list * Tried to use org.powermock for unit test * Update src/test/java/org/openrewrite/java/testing/mockito/ReplacePowerMockitoIntegrationTest.java Co-authored-by: Tim te Beek <[email protected]> * Update src/test/java/org/openrewrite/java/testing/mockito/ReplacePowerMockitoIntegrationTest.java * added unit test parser dependency to powermock * Add powermock jars for classpathFromResources * Removed additional Powermock annotations * Exclude Visual Studio Code settings from git * New Recipe PowerMockitoMockStaticToMockito - First it removes the PowerMockTestCaseConfig extension * Try to replace @PrepareForTest annotation with new MockedStatic fields * Give the test method a meaningful name * Mostly get the test cases passing. There is still a problem with the template which I think is a bug in OpenRewrite. * Get tests passing * Add missing license headers * Updated mockito.yml and IntegrationTest to reflect changes from last commit of code review * Added tearDown() methods to the refactored tests * Refactoring and code clean up * Fixed issue with missing statements in tearDown method. - Unit tests are failing because of missing type * Tried to replace Mockito.when with MockedStatic.when - Unit tests are failing because of missing type * Specified requirements in ReplacePowerMockitoIntegrationTest - Unit tests are failing because of missing type * Fixed unit tests and 1 integration test - The testNG case is still missing - Unit tests are failing because of missing type * First version of recipe to work with TestNG * Refactor test framework information holder and fix unit test issues * Enable ReplacePowerMockitoIntegrationTest and add testng-7.7.1 to classpathFromResources * Fix annotation pattern in yml file * Remove static inner class for annotation info and fix bugs * Fix issue with parameterized method return types in when statement refactoring * Fix issue when an unknown class is encountered while creating the MockedStatic fields * Remove rewriting of when method calls * New test for using PowerMockito without static import * Improved mockedStatic method invocations * Fixed NPE when visiting Interfaces or abstract classes * Unit test for NPE when visiting Interfaces or abstract classes * Fixed integration test * Additional fixes - Use TestNG as default test annotation - Improve storing of mocked types to prevent mock not getting initialized - Change name of generated setup method to prevent clashes - Correctly parse used mocks from annotation with pattern @PrepareForTest(Class1.class) - Add static import for Mockito.mockStatic even if "not used" - Add back when method rewriting - Rewrite PowerMock mock generation to use Mockito to prevent test runtime issues like ClassCastExceptions * Code formatting * Fixed all unit tests * Refactoring to reduce the complexity * Test powermockito calls are replaced in setUp methods * Add parameters to @AfterMethod annotation - replace close() with closeOnDemand() * Additional tests for testng tearDown method * Rearrange code * Replace PowerMockito.spy on static methods * Remove PowerMock extensions from test class * Fix ArgumentException when staticMock returns an array[] * Improved integration test - still not working * Fix issue with mockito static method not completely recognized * Rewrite PowerMocktio.mockStatic with dynamic method calls * Apply suggestions from code review * Only create mocked field, if mockStatic is acutally called for the class * Replace PowerMockito do-method calls with Mockito ones * Reformat code; fix typo in mockito.yml * Reformat code; Tests are now successful * Fixed unit tests after merge of master * Consider default implementations of interfaces * Replaced instanceof in filter lambdas with class::isInstance * Make use of visitors instead of parsing the class body * Setup and teardown method must have same group as the test method * Reduced cognitive complexity --------- Co-authored-by: Tim te Beek <[email protected]> Co-authored-by: Sam Snyder <[email protected]> Co-authored-by: Tim te Beek <[email protected]> Co-authored-by: D067517 <[email protected]> Co-authored-by: Tobias Pöppke <[email protected]>
1 parent a4fc572 commit d4e0b9d

File tree

10 files changed

+1221
-479
lines changed

10 files changed

+1221
-479
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
root = true
2+
3+
[*.java]
4+
indent_size = 4
5+
ij_continuation_indent_size = 2

src/main/java/org/openrewrite/java/testing/mockito/PowerMockitoMockStaticToMockito.java

Lines changed: 407 additions & 326 deletions
Large diffs are not rendered by default.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

src/main/resources/META-INF/rewrite/mockito.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,5 +171,25 @@ recipeList:
171171
fullyQualifiedTargetTypeName: org.mockito.Mockito
172172
returnType: org.mockito.MockedStatic
173173
matchOverrides: null
174+
matchUnknownTypes:
175+
- org.openrewrite.java.ChangeMethodTargetToStatic:
176+
methodPattern: org.powermock.api.mockito.PowerMockito do*(..)
177+
fullyQualifiedTargetTypeName: org.mockito.Mockito
178+
matchOverrides: null
179+
matchUnknownTypes: null
180+
- org.openrewrite.java.ChangeMethodTargetToStatic:
181+
methodPattern: org.powermock.api.mockito.PowerMockito mock(..)
182+
fullyQualifiedTargetTypeName: org.mockito.Mockito
183+
matchOverrides: null
184+
matchUnknownTypes: null
185+
- org.openrewrite.java.ChangeMethodTargetToStatic:
186+
methodPattern: org.powermock.api.mockito.PowerMockito spy(..)
187+
fullyQualifiedTargetTypeName: org.mockito.Mockito
188+
matchOverrides: null
189+
matchUnknownTypes: null
190+
- org.openrewrite.java.ChangeMethodTargetToStatic:
191+
methodPattern: org.powermock.api.mockito.PowerMockito when(..)
192+
fullyQualifiedTargetTypeName: org.mockito.Mockito
193+
matchOverrides: null
174194
matchUnknownTypes: null
175195
- org.openrewrite.java.testing.mockito.PowerMockitoMockStaticToMockito

src/test/java/org/openrewrite/java/testing/mockito/PowerMockitoMockStaticToMockitoTest.java

Lines changed: 265 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ public void defaults(RecipeSpec spec) {
3434
"junit-4.13.2",
3535
"junit-jupiter-api-5.9.2",
3636
"mockito-core-3.12.4",
37-
"powermock-api-mockito-1.7.4",
38-
"powermock-core-1.7.4"
37+
"powermock-api-mockito-1.6.5",
38+
"powermock-core-1.6.5",
39+
"testng-7.7.1"
3940
))
4041
.recipe(new PowerMockitoMockStaticToMockito());
4142
}
@@ -77,13 +78,13 @@ public class MyTest {
7778
private MockedStatic<Calendar> mockedCalendar;
7879
7980
@BeforeEach
80-
void setUp() {
81+
void setUpStaticMocks() {
8182
mockedCalendar = mockStatic(Calendar.class);
8283
}
8384
8485
@AfterEach
85-
void tearDown() {
86-
mockedCalendar.close();
86+
void tearDownStaticMocks() {
87+
mockedCalendar.closeOnDemand();
8788
}
8889
8990
@Test
@@ -137,15 +138,15 @@ class MyTest {
137138
private MockedStatic<Calendar> mockedCalendar;
138139
139140
@BeforeEach
140-
void setUp() {
141-
mockedCalendar = mockStatic(Calendar.class);
141+
void setUpStaticMocks() {
142142
mockedCurrency = mockStatic(Currency.class);
143+
mockedCalendar = mockStatic(Calendar.class);
143144
}
144145
145146
@AfterEach
146-
void tearDown() {
147-
mockedCalendar.close();
148-
mockedCurrency.close();
147+
void tearDownStaticMocks() {
148+
mockedCalendar.closeOnDemand();
149+
mockedCurrency.closeOnDemand();
149150
}
150151
151152
@Test
@@ -198,8 +199,170 @@ void testStaticMethod() {
198199
}
199200
200201
@AfterEach
201-
void tearDown() {
202-
mockedCalendar.close();
202+
void tearDownStaticMocks() {
203+
mockedCalendar.closeOnDemand();
204+
}
205+
}
206+
"""
207+
)
208+
);
209+
}
210+
211+
@Test
212+
void tearDownMethodOfTestNGHasAnnotationWithArgument() {
213+
//language=java
214+
rewriteRun(
215+
java(
216+
"""
217+
import java.util.Calendar;
218+
219+
import org.testng.annotations.Test;
220+
import org.powermock.core.classloader.annotations.PrepareForTest;
221+
222+
@PrepareForTest({Calendar.class})
223+
public class MyTest {
224+
225+
@Test
226+
void testSomething() { }
227+
228+
}
229+
""",
230+
"""
231+
import java.util.Calendar;
232+
233+
import org.testng.annotations.AfterMethod;
234+
import org.testng.annotations.BeforeMethod;
235+
import org.testng.annotations.Test;
236+
237+
public class MyTest {
238+
239+
@BeforeMethod
240+
void setUpStaticMocks() {
241+
}
242+
243+
@AfterMethod(alwaysRun = true)
244+
void tearDownStaticMocks() {
245+
}
246+
247+
@Test
248+
void testSomething() { }
249+
250+
}
251+
"""
252+
)
253+
);
254+
}
255+
@Test
256+
void tearDownMethodOfTestNGWithAnnotationRemainsUntouched() {
257+
//language=java
258+
rewriteRun(
259+
java(
260+
"""
261+
import java.util.Calendar;
262+
263+
import org.testng.annotations.AfterMethod;
264+
import org.testng.annotations.Test;
265+
import org.powermock.core.classloader.annotations.PrepareForTest;
266+
267+
@PrepareForTest({Calendar.class})
268+
public class MyTest {
269+
270+
@AfterMethod(groups = "irrelevant")
271+
void tearDown() {}
272+
273+
@Test
274+
void testSomething() { }
275+
276+
}
277+
""",
278+
"""
279+
import java.util.Calendar;
280+
281+
import org.testng.annotations.AfterMethod;
282+
import org.testng.annotations.BeforeMethod;
283+
import org.testng.annotations.Test;
284+
285+
public class MyTest {
286+
287+
@AfterMethod(groups = "irrelevant")
288+
void tearDown() {}
289+
290+
@BeforeMethod
291+
void setUpStaticMocks() {
292+
}
293+
294+
@Test
295+
void testSomething() { }
296+
297+
}
298+
"""
299+
)
300+
);
301+
}
302+
@Test
303+
void tearDownMethodOfTestNGHasAnnotationWithSameArgumentsAsTheTestThatCallsMockStatic() {
304+
//language=java
305+
rewriteRun(
306+
java(
307+
"""
308+
import java.util.Calendar;
309+
310+
import static org.mockito.Mockito.*;
311+
312+
import org.testng.annotations.AfterMethod;
313+
import org.testng.annotations.BeforeMethod;
314+
import org.testng.annotations.Test;
315+
import org.powermock.core.classloader.annotations.PrepareForTest;
316+
317+
@PrepareForTest({Calendar.class})
318+
public class MyTest {
319+
320+
private Calendar calendarMock;
321+
322+
@Test(groups = "irrelevant")
323+
void testSomethingIrrelevantForCheckin() { }
324+
325+
@Test(groups = "checkin")
326+
void testStaticMethod() {
327+
calendarMock = mock(Calendar.class);
328+
mockStatic(Calendar.class);
329+
when(Calendar.getInstance()).thenReturn(calendarMock);
330+
}
331+
}
332+
""",
333+
"""
334+
import java.util.Calendar;
335+
336+
import static org.mockito.Mockito.*;
337+
338+
import org.mockito.MockedStatic;
339+
import org.testng.annotations.AfterMethod;
340+
import org.testng.annotations.BeforeMethod;
341+
import org.testng.annotations.Test;
342+
343+
public class MyTest {
344+
345+
private MockedStatic<Calendar> mockedCalendar;
346+
347+
private Calendar calendarMock;
348+
349+
@BeforeMethod(groups = "checkin")
350+
void setUpStaticMocks() {
351+
mockedCalendar = mockStatic(Calendar.class);
352+
}
353+
354+
@AfterMethod(groups = "checkin")
355+
void tearDownStaticMocks() {
356+
mockedCalendar.closeOnDemand();
357+
}
358+
359+
@Test(groups = "irrelevant")
360+
void testSomethingIrrelevantForCheckin() { }
361+
362+
@Test(groups = "checkin")
363+
void testStaticMethod() {
364+
calendarMock = mock(Calendar.class);
365+
mockedCalendar.when(Calendar::getInstance).thenReturn(calendarMock);
203366
}
204367
}
205368
"""
@@ -284,6 +447,7 @@ void testStaticMethod() {
284447
)
285448
);
286449
}
450+
287451
@Test
288452
void argumentOfVerifyOnParameterlessStaticMethodIsReplacedBySimpleLambda() {
289453
//language=java
@@ -312,29 +476,97 @@ void testStaticMethod() {
312476
}
313477
""",
314478
"""
315-
import static org.mockito.Mockito.*;
316-
317-
import java.util.Currency;
318-
import java.util.Locale;
319-
320-
import org.junit.jupiter.api.Test;
321-
import org.mockito.MockedStatic;
322-
323-
public class MyTest {
324-
325-
private MockedStatic<Currency> mockedCurrency;
326-
327-
private Currency currencyMock = mock(Currency.class);
328-
329-
@Test
330-
void testStaticMethod() {
331-
mockedCurrency.verify(() -> Currency.getInstance(Locale.ENGLISH), never());
332-
mockedCurrency.verify(Currency::getAvailableCurrencies, atLeastOnce());
333-
}
334-
}
335-
"""
479+
import static org.mockito.Mockito.*;
480+
481+
import java.util.Currency;
482+
import java.util.Locale;
483+
484+
import org.junit.jupiter.api.Test;
485+
import org.mockito.MockedStatic;
486+
487+
public class MyTest {
488+
489+
private MockedStatic<Currency> mockedCurrency;
490+
491+
private Currency currencyMock = mock(Currency.class);
492+
493+
@Test
494+
void testStaticMethod() {
495+
mockedCurrency.verify(() -> Currency.getInstance(Locale.ENGLISH), never());
496+
mockedCurrency.verify(Currency::getAvailableCurrencies, atLeastOnce());
497+
}
498+
}
499+
"""
336500
)
337501
);
338502
}
339503

504+
@Test
505+
void interfacesAndAbstractClassesWithEmptyMethodBodiesRemainsUntouched() {
506+
//language=java
507+
rewriteRun(java(
508+
"""
509+
public interface MyInterface {
510+
511+
void checkThis();
512+
513+
}
514+
""")
515+
, java(
516+
"""
517+
public abstract class MyAbstractClass {
518+
519+
public boolean isItTrue() { return true; }
520+
521+
public abstract boolean isItImplemented();
522+
523+
}
524+
"""
525+
));
526+
}
527+
528+
@Test
529+
void extensionOfPowerMockTestCaseGetsRemoved() {
530+
//language=java
531+
rewriteRun(java(
532+
"""
533+
package org.powermock.modules.testng;
534+
535+
public class PowerMockTestCase {}
536+
"""
537+
),
538+
java(
539+
"""
540+
import org.powermock.modules.testng.PowerMockTestCase;
541+
542+
public class MyPowerMockTestCase extends PowerMockTestCase {}
543+
""",
544+
"""
545+
public class MyPowerMockTestCase {}
546+
""")
547+
);
548+
}
549+
550+
@Test
551+
void extensionOfPowerMockConfigurationGetsRemoved() {
552+
//language=java
553+
rewriteRun(
554+
java(
555+
"""
556+
package org.powermock.configuration;
557+
558+
public class PowerMockConfiguration {}
559+
"""
560+
),
561+
java(
562+
"""
563+
import org.powermock.configuration.PowerMockConfiguration;
564+
565+
public class MyPowerMockConfiguration extends PowerMockConfiguration {}
566+
""",
567+
"""
568+
public class MyPowerMockConfiguration {}
569+
"""
570+
));
571+
}
340572
}

0 commit comments

Comments
 (0)