Skip to content

Problem with classpath in multi-module projects: Runtime conflict of dependencies #31

@indeterminatus

Description

@indeterminatus

In a multi-module project, the generated classpath collects all dependencies of all modules, even though the test-class to mutate "lives" in only one of them.

This is especially problematic when one of the modules contains a "toxic" dependency that conflicts with other modules at runtime.

For example, "log4j-slf4j-impl" and "log4j-to-slf4j" cannot co-exist at runtime, but if one module depends on the first, and one on the latter, no test can be mutated.

An excerpt of the verbose log of PIT:

08:56:32 PIT >> INFO : MINION : 08:56:32 PIT >> FINE : Gathering coverage for test Description [testClass=net.dashumankapital.a.DemoTest, name=[engine:junit-jupiter]/[class:net.dashumankapital.a.DemoTest]/[method:justChecking()]]
08:56:32 PIT >> INFO : MINION : 08:56:32 PIT >> SEVERE : Description [testClass=net.dashumankapital.a.DemoTest, name=[engine:junit-jupiter]/[class:net.dashumankapital.a.DemoTest]/[method:justChecking()]]
08:56:32 PIT >> INFO : MINION : java.lang.ExceptionInInitializerError
08:56:32 PIT >> INFO : MINION : 	at net.dashumankapital.a.DemoTest.justChecking(DemoTest.java:11)
08:56:32 PIT >> INFO : MINION : 	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
08:56:32 PIT >> INFO : MINION : 	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
08:56:32 PIT >> INFO : MINION : 	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
08:56:32 PIT >> INFO : MINION : Caused by: org.apache.logging.log4j.LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4j
08:56:32 PIT >> INFO : MINION : 	at org.apache.logging.slf4j.Log4jLoggerFactory.validateContext(Log4jLoggerFactory.java:67)
08:56:32 PIT >> INFO : MINION : 	at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:49)
08:56:32 PIT >> INFO : MINION : 	at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:32)
08:56:32 PIT >> INFO : MINION : 	at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:52)
08:56:32 PIT >> INFO : MINION : 	at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:32)
08:56:32 PIT >> INFO : MINION : 	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:363)
08:56:32 PIT >> INFO : MINION : 	at org.apache.logging.slf4j.SLF4JLoggerContext.getLogger(SLF4JLoggerContext.java:39)
08:56:32 PIT >> INFO : MINION : 	at org.apache.logging.log4j.spi.LoggerContext.getLogger(LoggerContext.java:46)
08:56:32 PIT >> INFO : MINION : 	at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:555)
08:56:32 PIT >> INFO : MINION : 	at net.dashumankapital.a.Demo.<clinit>(Demo.java:7)
08:56:32 PIT >> INFO : MINION : 	... 4 more

I will attach a small sample project that demonstrates this.

Pick either of the test classes. "Normal" test execution works just fine. The sample project is naturally bogus, the most important bit is that neither module pulls in both dependencies, but in combination they do, and they do not depend on each other.

My "real" project consists of many modules, some of them totally independent, containing legacy stuff. And of those, one of them uses such "toxic" dependency (which I cannot get easily rid of). Since there is no Maven/dependency trickery to pull that I'm aware of, this effectively prevents mutating any test class of the entire project.

My proposed solution would be to use only the modules for classpath-file generation that are actually needed by the test(s).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions