From 3a4d0da79d54275ec19dcd9fdf10b2105ea810c3 Mon Sep 17 00:00:00 2001 From: Filip Hrisafov Date: Fri, 5 Jun 2026 16:34:05 +0200 Subject: [PATCH] Improve JavaFileAssert#hasSameMapperContent to include File Information for the diff The FileInfo from Open Test Alliance for the JVM allows the IDE to display a diff between 2 files nicely in the UI. This makes it easier to compare failing fixtures and immediately copy what you want to the fixture. Also improve the loading of the expected fixture from the resource folder instead of the compilation folder --- .../testutil/assertions/JavaFileAssert.java | 18 ++++++++++++++- .../testutil/runner/CompilingExtension.java | 2 +- .../ap/testutil/runner/GeneratedSource.java | 23 ++++++++----------- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java b/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java index 2f8b13ba25..277b552f72 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java @@ -10,6 +10,7 @@ import java.io.UncheckedIOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; @@ -18,6 +19,7 @@ import org.assertj.core.internal.Diff; import org.assertj.core.internal.Failures; import org.assertj.core.util.diff.Delta; +import org.opentest4j.FileInfo; import static java.lang.String.format; @@ -81,8 +83,22 @@ public void hasSameMapperContent(File expected) { ) ); diffs.removeIf( this::ignoreDelta ); if ( !diffs.isEmpty() ) { + FileInfo actualInfo; + FileInfo expectedInfo; + try { + actualInfo = new FileInfo( actual.getAbsolutePath(), Files.readAllBytes( actual.toPath() ) ); + expectedInfo = new FileInfo( expected.getAbsolutePath(), Files.readAllBytes( expected.toPath() ) ); + } + catch ( IOException e ) { + throw new RuntimeException( e ); + } throw Failures.instance() - .failure( info, ShouldHaveSameContent.shouldHaveSameContent( actual, expected, diffs ) ); + .failure( + info, + ShouldHaveSameContent.shouldHaveSameContent( actual, expected, diffs ), + actualInfo, + expectedInfo + ); } } catch ( IOException e ) { diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingExtension.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingExtension.java index 468e2908a1..eb18615b8b 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingExtension.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingExtension.java @@ -674,7 +674,7 @@ boolean needsRecompilation(CompilationRequest compilationRequest, CompilationCac return !compilationRequest.equals( compilationCache.getLastRequest() ); } - private static String getBasePath() { + static String getBasePath() { try { return new File( "." ).getCanonicalPath(); } diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/GeneratedSource.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/GeneratedSource.java index 85b6ec80fd..7c6c447d77 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/GeneratedSource.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/GeneratedSource.java @@ -6,9 +6,6 @@ package org.mapstruct.ap.testutil.runner; import java.io.File; -import java.net.URL; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -19,6 +16,7 @@ import static org.assertj.core.api.Assertions.fail; import static org.mapstruct.ap.testutil.runner.CompilingExtension.NAMESPACE; +import static org.mapstruct.ap.testutil.runner.CompilingExtension.getBasePath; /** * A {@link org.junit.jupiter.api.extension.RegisterExtension RegisterExtension} to perform assertions on generated @@ -36,6 +34,7 @@ public class GeneratedSource implements BeforeTestExecutionCallback, AfterTestExecutionCallback { private static final String FIXTURES_ROOT = "fixtures/"; + private static final String FIXTURES_DIR = getBasePath() + "/src/test/resources/fixtures/"; /** * ThreadLocal, as the source dir must be injected for this extension to gain access @@ -139,8 +138,8 @@ public JavaFileAssert forJavaFile(String path) { private void handleFixtureComparison() { for ( FixtureComparison fixture : fixturesFor ) { String fixtureName = getFixtureName( fixture.mapperClass, fixture.variant ); - URL expectedFile = getExpectedResource( fixtureName ); - if ( expectedFile == null ) { + File expectedFile = getExpectedResource( fixtureName ); + if ( !expectedFile.exists() ) { fail( String.format( "No reference file could be found for Mapper %s. You should create a file %s", fixture.mapperClass.getName(), @@ -148,8 +147,7 @@ private void handleFixtureComparison() { ) ); } else { - File expectedResource = new File( URLDecoder.decode( expectedFile.getFile(), StandardCharsets.UTF_8 ) ); - forMapper( fixture.mapperClass ).hasSameMapperContent( expectedResource ); + forMapper( fixture.mapperClass ).hasSameMapperContent( expectedFile ); } } } @@ -159,16 +157,15 @@ private String getFixtureName(Class mapperClass, String variant) { return mapperClass.getName().replace( '.', '/' ).concat( suffix ); } - private URL getExpectedResource(String fixtureName) { - ClassLoader classLoader = getClass().getClassLoader(); + private File getExpectedResource(String fixtureName) { for ( int version = Runtime.version().feature(); version >= 11 && compiler != Compiler.ECLIPSE; version-- ) { - URL resource = classLoader.getResource( FIXTURES_ROOT + "/" + version + "/" + fixtureName ); - if ( resource != null ) { - return resource; + File fixtureFile = new File( FIXTURES_DIR + version + File.separator + fixtureName ); + if ( fixtureFile.exists() ) { + return fixtureFile; } } - return classLoader.getResource( FIXTURES_ROOT + fixtureName ); + return new File( FIXTURES_DIR + fixtureName ); } private static final class FixtureComparison {