Eliminating tedium with OpenRewrite
refactoring development developer experience automationI find some tasks so tedious that I tend to avoid them. For example, I’ve recently been working on a sample application for a new, soon to be released Eventuate saga framework (more on that later). I’d created the application by copying another sample that was still using JUnit 4. But I’d been putting off updating the tests to JUnit 5. That is, until today, when I got it done in a few minutes using OpenRewrite.
What is OpenRewrite?
OpenRewrite is a tool for refactoring Java code. It runs recipes that transform your source code. By running a single command, you can quickly and reliably make what would otherwise be very time-consuming changes to your code base.
There is a comprehensive collection of recipes available. I’d previously used it to migrate an application to Spring Boot 3. There’s also a recipe for migrating a Spring Boot application from JUnit 4 to JUnit 5.
Running OpenRewrite
There are a few different ways to run OpenRewrite.
Many examples modify your pom.xml
or build.gradle
files.
But since you typically run a recipe once, my preferred approach is to use a Gradle init script.
This allows me to run OpenRewrite from the command line without modifying my project.
The Gradle init script for running OpenRewrite
Here’s the Gradle init script (copied from the OpenRewrite docs) that I used to run the JUnit 4 to JUnit 5 migration recipe:
initscript {
repositories {
maven { url "https://plugins.gradle.org/m2" }
}
dependencies {
classpath("org.openrewrite:plugin:latest.release")
}
}
rootProject {
plugins.apply(org.openrewrite.gradle.RewritePlugin)
dependencies {
rewrite("org.openrewrite.recipe:rewrite-spring:latest.release")
}
afterEvaluate {
if (repositories.isEmpty()) {
repositories {
mavenCentral()
}
}
}
}
The script declares org.openrewrite.recipe:rewrite-spring
, which contains the needed recipe, as a dependency.
Running the recipe
Here’s the shell command that I used to run OpenRewrite:
./gradlew rewriteRun --init-script <path to initscript> \
-Drewrite.activeRecipe=org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration \
-Dorg.gradle.jvmargs=-Xmx8G
This command runs the rewriteRun
task, which is defined by the init script.
The rewrite.activeRecipe
property specifies the recipe to run.
I needed to increase the heap size to prevent OpenRewrite from running out of memory.
The results
The recipe made numerous changes to the code base including:
- Updating the
build.gradle
dependencies - Fixing the imports
- Removing
@RunWith(SpringJUnit4ClassRunner.class)
annotations - Replacing
@RunWith(MockitoJUnitRunner.class)
with@ExtendWith(MockitoExtension.class)
- Replacing
@Before
with@BeforeEach
The only thing I needed to do was change some testing related plugins to use useJUnitPlatform()
.
Pretty awesome! OpenRewrite estimated that it saved me 55 minutes of work.
The code
Here’s a handy shell script that migrates your project from JUnit 4 to JUnit 5.
Need help with accelerating software delivery?
I’m available to help your organization improve agility and competitiveness through better software architecture: training workshops, architecture reviews, etc.