Search code examples
javamockitomaven-surefire-pluginjava-17

How to Mockito.spy on Graphics2D in Java 17


I have a maven project that should run on java-8, java-11. I want to add support for java-17 and I have some issues with testing.

Simplified version of the test looks like:

@Test
public void testGraphics() throws Exception {
  BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
  Graphics2D graphics = Mockito.spy(bi.createGraphics());

  //my code for testing
  graphics.getColor();

  Mockito.verify(graphics, times(1)).getColor();
}

I execute test with:

mvn clean compile test

This works fine on java 8 and java 11. However, in java 17 I get:

java.lang.IllegalAccessException: class org.mockito.internal.util.reflection.ReflectionMemberAccessor cannot access class sun.java2d.SunGraphics2D (in module java.desktop) because module java.desktop does not export sun.java2d to unnamed module @62bd2070

This can be fixed by adding --add-opens=java.desktop/sun.java2d=ALL-UNNAMED to test command:

mvn clean compile test -DargLine=--add-opens=java.desktop/sun.java2d=ALL-UNNAMED

However, this command would not work on java 8 because it does not recognize --add-opens option:

Unrecognized option: --add-opens=java.desktop/sun.java2d=ALL-UNNAMED
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

My continuous integration is a matrix of running the same tests in different environments (different java version, different databases, etc) and I would prefer to avoid having different maven options depending on the environment.

Is there another way to run this test that does not require changing maven parameters in different java versions? I cannot use Mockito.mock because my code interacts with the graphics object and depends on the result (and there are many calls so mocking each one of them is not an option for the moment). Here are options that I considered but could not find a way to do it:

  • use different implementation of Graphics2D instead of sun.java2d.SunGraphics2D
  • modify pom.xml to conditionally provide options to surefire plugin depending on the java version
  • force surefire to ignore unrecognized options

For the record I'm using junit 4.12 and mockito 4.6.1


Solution

  • One way of doing it is to provide surefire with an option that asks java to ignore unrecognized option. It can be done using following command:

    mvn clean compile test -DargLine="--add-opens=java.desktop/sun.java2d=ALL-UNNAMED -XX:+IgnoreUnrecognizedVMOptions"