Motivation
Recently I want to migrate from JUnitassertEquals
to HamcrestassertThat
andis
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 chooseJavaParser.
Objective
Here is how existing test looks like.
packagecom.franzwong.playground;importorg.junit.jupiter.api.Test;importstaticorg.junit.jupiter.api.Assertions.assertEquals;classMyTest{@Testpublicvoidtest(){Stringa="123";assertEquals("123",a);}}
I would like to change it to something like this.
packagecom.franzwong.playground;importorg.junit.jupiter.api.Test;importstaticorg.hamcrest.MatcherAssert.assertThat;importstaticorg.hamcrest.CoreMatchers.is;classMyTest{@Testpublicvoidtest(){Stringa="123";assertThat(a,is("123"));}}
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>
SetupCompilationUnit
SupposeMyTest.java
file is stored in/tmp
folder.
SourceRootsourceRoot=newSourceRoot(Path.of("/tmp"));CompilationUnitcu=sourceRoot.parse("","MyTest.java");
Remove the static import ofassertEquals
We just need to walk through the syntax tree. If the import declaration node is found and it is theassertEquals
node, we just remove it.
cu.walk(ImportDeclaration.class,e->{if(e.isStatic()&&"org.junit.jupiter.api.Assertions.assertEquals".equals(e.getNameAsString())){e.remove();}});
Add static import forassertThat
andis
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(newImportDeclaration("org.hamcrest.MatcherAssert.assertThat",true,false));cu.addImport(newImportDeclaration("org.hamcrest.CoreMatchers.is",true,false));
ConvertassertEquals("123", a)
toassertThat(a, is("123"))
We walk through the syntax tree again. If it is aMethodCallExpr
node and its name isassertEquals
, we rename it and change its parameters.
cu.walk(MethodCallExpr.class,e->{if(!"assertEquals".equals(e.getNameAsString())){return;}// Rename methode.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 itMethodCallExprisMethod=newMethodCallExpr("is",equalsArgments.get(0));// Change the parametersequalsArgments.set(0,equalsArgments.get(1));equalsArgments.set(1,isMethod);});
Save modified source
We just need to provide a folder path to it.
sourceRoot.saveAll(Path.of("/tmp/output"));
So that's it. Here is how the whole source code looks like. I hope this tutorial is useful to you.
publicstaticvoidmain(String[]args){SourceRootsourceRoot=newSourceRoot(Path.of("/tmp"));CompilationUnitcu=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(newImportDeclaration("org.hamcrest.MatcherAssert.assertThat",true,false));cu.addImport(newImportDeclaration("org.hamcrest.CoreMatchers.is",true,false));cu.walk(MethodCallExpr.class,e->{if(!"assertEquals".equals(e.getNameAsString())){return;}// Rename methode.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 itMethodCallExprisMethod=newMethodCallExpr("is",equalsArgments.get(0));// Change the parametersequalsArgments.set(0,equalsArgments.get(1));equalsArgments.set(1,isMethod);});sourceRoot.saveAll(Path.of("/tmp/output"));}
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse