Motivation
Recently I want to migrate from JUnit assertEquals
to Hamcrest assertThat
and is
to improve readability of my unit tests.
Instead of using regular expression, it seems it is safer to parse the syntax and manipulate it, so I choose JavaParser.
Objective
Here is how existing test looks like.
package com.franzwong.playground;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class MyTest {
@Test
public void test() {
String a = "123";
assertEquals("123", a);
}
}
Enter fullscreen mode Exit fullscreen mode
I would like to change it to something like this.
package com.franzwong.playground;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.is;
class MyTest {
@Test
public void test() {
String a = "123";
assertThat(a, is("123"));
}
}
Enter fullscreen mode Exit fullscreen mode
Action items:
- Remove the static import of
assertEquals
- Add static import for
assertThat
andis
- Convert
assertEquals("123", a)
toassertThat(a, is("123"))
- Save modified source
Solution
Add Maven dependency for JavaParser
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>3.16.2</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode
Setup CompilationUnit
Suppose MyTest.java
file is stored in /tmp
folder.
SourceRoot sourceRoot = new SourceRoot(Path.of("/tmp"));
CompilationUnit cu = sourceRoot.parse("", "MyTest.java");
Enter fullscreen mode Exit fullscreen mode
Remove the static import of assertEquals
We just need to walk through the syntax tree. If the import declaration node is found and it is the assertEquals
node, we just remove it.
cu.walk(ImportDeclaration.class, e -> {
if (e.isStatic() && "org.junit.jupiter.api.Assertions.assertEquals".equals(e.getNameAsString())) {
e.remove();
}
});
Enter fullscreen mode Exit fullscreen mode
Add static import for assertThat
and is
Parameters of ImportDeclaration constructor
- 1st parameter is the static method name
- 2nd parameter is true if it is a static import
- 3rd parameter is true if it is asterisk
cu.addImport(new ImportDeclaration("org.hamcrest.MatcherAssert.assertThat", true, false));
cu.addImport(new ImportDeclaration("org.hamcrest.CoreMatchers.is", true, false));
Enter fullscreen mode Exit fullscreen mode
Convert assertEquals("123", a)
to assertThat(a, is("123"))
We walk through the syntax tree again. If it is a MethodCallExpr
node and its name is assertEquals
, we rename it and change its parameters.
cu.walk(MethodCallExpr.class, e -> {
if (!"assertEquals".equals(e.getNameAsString())) {
return;
}
// Rename method
e.setName("assertThat");
// Get the parameter list of `assertEquals`
NodeList<Expression> equalsArgments = e.getArguments();
// Create a new `is` method and assign 1st parameter of `assertEquals` to it
MethodCallExpr isMethod = new MethodCallExpr("is", equalsArgments.get(0));
// Change the parameters
equalsArgments.set(0, equalsArgments.get(1));
equalsArgments.set(1, isMethod);
});
Enter fullscreen mode Exit fullscreen mode
Save modified source
We just need to provide a folder path to it.
sourceRoot.saveAll(Path.of("/tmp/output"));
Enter fullscreen mode Exit fullscreen mode
So that’s it. Here is how the whole source code looks like. I hope this tutorial is useful to you.
public static void main(String[] args) {
SourceRoot sourceRoot = new SourceRoot(Path.of("/tmp"));
CompilationUnit cu = sourceRoot.parse("", "MyTest.java");
cu.walk(ImportDeclaration.class, e -> {
if (e.isStatic() && "org.junit.jupiter.api.Assertions.assertEquals".equals(e.getNameAsString())) {
e.remove();
}
});
cu.addImport(new ImportDeclaration("org.hamcrest.MatcherAssert.assertThat", true, false));
cu.addImport(new ImportDeclaration("org.hamcrest.CoreMatchers.is", true, false));
cu.walk(MethodCallExpr.class, e -> {
if (!"assertEquals".equals(e.getNameAsString())) {
return;
}
// Rename method
e.setName("assertThat");
// Get the parameter list of `assertEquals`
NodeList<Expression> equalsArgments = e.getArguments();
// Create a new `is` method and assign 1st parameter of `assertEquals` to it
MethodCallExpr isMethod = new MethodCallExpr("is", equalsArgments.get(0));
// Change the parameters
equalsArgments.set(0, equalsArgments.get(1));
equalsArgments.set(1, isMethod);
});
sourceRoot.saveAll(Path.of("/tmp/output"));
}
Enter fullscreen mode Exit fullscreen mode
暂无评论内容