A Groovy Extension Module that makes JUnit 5 and 6 assertions more Groovy-friendly by adding BigDecimal-aware comparisons and GString/String assertEquals support.
This library extends JUnit's Assertions class with
- BigDecimal-aware assertion methods.
Use numerical comparison instead of strict equality. This solves the common problem where
new BigDecimal("5.0")andnew BigDecimal("5.00")are not considered equal by the standardassertEqualsmethod, even though they represent the same numerical value. assertEqualsoverloads forStringandGString(added inv0.3.0). This is especially useful in@CompileStaticcode, where JUnit can otherwise get confused by Groovy'sStringandGStringtypes.- Optional Groovy-friendly classloader support for JUnit Platform launching (for example when using
@Grab/Grapeat runtime)
- Scale-insensitive BigDecimal comparison: Compares BigDecimals using
compareTo()instead ofequals() GString/Stringcompatibility: Compares interpolated Groovy strings and plain Java strings inassertEquals- Seamless integration: Works automatically via Groovy's Extension Module mechanism
- Multiple overloads: Supports BigDecimal equality, BigDecimal delta assertions, and
String/GStringcombinations - JUnit 5 compatible: Extends the standard
org.junit.jupiter.api.Assertionsclass
Add the following dependency to your build.gradle:
dependencies {
testImplementation 'se.alipsa.groovy:groovier-junit:0.3.0'
}For Kotlin DSL (build.gradle.kts):
dependencies {
testImplementation("se.alipsa.groovy:groovier-junit:0.3.0")
}Add the following dependency to your pom.xml:
<dependency>
<groupId>se.alipsa.groovy</groupId>
<artifactId>groovier-junit</artifactId>
<version>0.3.0</version>
<scope>test</scope>
</dependency>Once the library is on your classpath, the extension methods are automatically available. No additional configuration is needed.
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
class MyTest {
@Test
void testBigDecimalComparison() {
// These assertions now pass, comparing numerical values instead of scale
Assertions.assertEquals(5.0, 5.00G)
Assertions.assertEquals(new BigDecimal("5.0"), new BigDecimal("5.00"))
// Works with different Number types
Assertions.assertEquals(5, 5.00G)
Assertions.assertEquals(5.0d, 5.00G)
Assertions.assertEquals(5L, 5.00G)
Assertions.assertEquals(5G, 5.00G)
}
@Test
void testWithCustomMessage() {
// Custom failure messages are supported
Assertions.assertEquals(100, 100.00G, "Account balance mismatch")
}
@Test
void testBigDecimalWithDelta() {
Assertions.assertEquals(10, 10.04G, 0.05G)
}
@Test
void testStringAndGStringComparison() {
String expected = 'Hello World'
GString actual = "${expected}"
Assertions.assertEquals(expected, actual)
Assertions.assertEquals(actual, expected, "Interpolated text should match")
}
}The String/GString overloads are mainly relevant in statically compiled Groovy, where method selection can otherwise fail even though the values are textually equal.
The assertion extensions work with zero extra setup.
If you also want Groovy-friendly classloader behavior for JUnit Platform launching (for example when using @Grab/Grape at runtime), enable the optional launcher interceptor.
groovier.junit.classloader.enabled(default:false)groovier.junit.classloader.mode(optional:contextorroot, default:context)groovier.junit.classloader.debug(optional:trueto print debug logs)
test {
useJUnitPlatform()
// Enable JUnit launcher interceptor auto-detection
systemProperty 'junit.platform.launcher.interceptors.enabled', 'true'
// Opt in to groovier-junit classloader support
systemProperty 'groovier.junit.classloader.enabled', 'true'
systemProperty 'groovier.junit.classloader.mode', 'context'
}For @GrabConfig(systemClassLoader=true), the JVM must start with RootLoader as system classloader:
test {
useJUnitPlatform()
systemProperty 'junit.platform.launcher.interceptors.enabled', 'true'
systemProperty 'groovier.junit.classloader.enabled', 'true'
systemProperty 'groovier.junit.classloader.mode', 'root'
jvmArgs '-Djava.system.class.loader=org.codehaus.groovy.tools.RootLoader'
}<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.4</version>
<configuration>
<systemPropertyVariables>
<junit.platform.launcher.interceptors.enabled>true</junit.platform.launcher.interceptors.enabled>
<groovier.junit.classloader.enabled>true</groovier.junit.classloader.enabled>
<groovier.junit.classloader.mode>context</groovier.junit.classloader.mode>
</systemPropertyVariables>
</configuration>
</plugin>For @GrabConfig(systemClassLoader=true), add:
<argLine>-Djava.system.class.loader=org.codehaus.groovy.tools.RootLoader</argLine>- This feature is opt-in and does not affect users who only want assertion extensions.
- The interceptor can switch context classloader during launcher operations.
- It cannot retroactively replace the JVM system classloader after startup.
The extension uses Groovy's Extension Module mechanism to add static methods to JUnit's Assertions class. When you call Assertions.assertEquals(), Groovy automatically dispatches to the matching enhanced overload for BigDecimal-aware comparison or String/GString conversion.
Standard JUnit behavior (without this extension):
assertEquals(new BigDecimal("5.0"), new BigDecimal("5.00")) // FAILS - different scaleWith groovier-junit:
assertEquals(new BigDecimal("5.0"), new BigDecimal("5.00")) // PASSES - numerical equality
assertEquals('Hello World', "${'Hello World'}") // PASSES - GString converted to String- Java: 17 or higher
- Groovy: any 4.x or 5.x version should work
- JUnit: any 6.x version should work (probably earlier versions too)
git clone https://github.com/Alipsa/groovier-junit.git
cd groovier-junit
./gradlew buildGenerate GroovyDoc documentation:
./gradlew antGroovydocThe documentation will be available in build/groovydocant/.
This project is licensed under the MIT License.
Contributions are welcome! Please feel free to submit a Pull Request.
Per Nyfelt