4

I'm using Java9 Module system (running on openjdk11)

I have

  • migrated from Java8 and the code contained classes that made use of the ServiceLoader mechanism.
  • a unit test for this class which tries to load two test service implementations

  • the test implementations are listed in META-INF/services file

src/main/example/Service.java

public interface Service {
  public static List<Service> loadServices(){
    return StreamSupport.stream(ServiceLoader.load(Service.class).spliterator(),false)                                       
                        .collect(Collectors.toList());
   }
}

and a src/main/module-info.java

module example {
  uses example.Service;
  exports example;
}

and I have a unit test like this

src/main/example/ServiceTest.java

public ServiceTest {
  @Test
  void loadServices_should_find_TestServices{
    List<Service> services = Service.loadServices();
    assertEquals(2, services.size());
  }
}

and I have two test services in the test source:

src/main/example/TestService1.java

public TestService1 implements Service {}

src/main/example/TestService2.java

public TestService2 implements Service {}

src/test/resources/META-INF/services/example.Service

example.TestService1
example.TestService2

I'm using the maven-surefire-plugin 3.0.0-M3 without any specific configuration

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>3.0.0-M3</version>
</plugin>

which properly patches the example module (from surefireargs file)

--patch-module example="D:\\git\\example\\target\\test-classes"

When I execute the test in IntelliJ directly, the test run successfully, finding two services. However, when I build the module in maven and the test is executed by surefire, it doesn't find the services and the test fails.

How am I supposed to configure surefire to find the TestServices located in the test sources? I can not define a "provides ..." declaration in the module info as they are test services. What am I doing wrong?

Gerald Mücke
  • 10,724
  • 2
  • 50
  • 67
  • 1
    To test TestService1 and TestService2 would require putting them into their own test module with the appropriate `provides` clause. The JDK doesn't have a `--add-provides` option to augment the set of services that a module provides. There are chicken 'n egg with such an option because service binding is part of resolution and is done long before command line options to augment the module graph are handled. – Alan Bateman Jan 09 '19 at 07:24
  • 2
    In passing, look at the ServiceLoader::stream method, this should reduce your code fragment to: `ServiceLoader.load(Service.class).stream().collect(Collectors.toList());` – Alan Bateman Jan 09 '19 at 07:25

1 Answers1

2

I found a workaround, which I don't really consider an actual solution to the problem: Disabling the ModulePath in surefire, reverting back to ClassPath:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <useModulePath>false</useModulePath>
  </configuration>
</plugin>
Gerald Mücke
  • 10,724
  • 2
  • 50
  • 67