Verify dependencies in a Maven build
Is there a way to write a test that checks Maven dependencies?
In our project, we found these problems:
开发者_运维问答Some parts of the project use
commons-io:commons-io
, others usedorg.apache.commons:commons-io
The wrong version of a dependency was used
stax
uses the versions1.0-2
and1.0.1
. Using the automatic dependency resolution,1.0-2
wins.
So what I want is to write a test case which takes the current dependency tree as input and runs a couple of checks on it. Is that possible?
@Test
public void testCommonsIo() throws Exception {
assertDependencyVersion("commons-io", "commons-io", "2.0");
}
private void assertDependencyVersion(final String groupId,
final String artifactId, final String expectedVersion)
throws IOException {
final StringBuilder sb = new StringBuilder("/META-INF/maven/");
sb.append(groupId).append("/").append(artifactId);
sb.append("/pom.properties");
final String resourcePath = sb.toString();
final InputStream propertiesStream = this.getClass()
.getResourceAsStream(resourcePath);
assertNotNull("no dependency found: " + groupId + ":" + artifactId,
propertiesStream);
final Properties properties = new Properties();
properties.load(propertiesStream);
assertEquals("group", groupId, properties.getProperty("groupId"));
assertEquals("artifact", artifactId, properties.getProperty("artifactId"));
assertEquals("version", expectedVersion, properties.getProperty("version"));
}
Check this answer too.
Here is an assert method for StAX and other dependencies which don't contain pom.properties
just manifest.mf
. Maybe it would worth caching the Properties
instances if there are lots of assertDependencyByMetaInf
calls.
@Test
public void testStaxDependency() throws Exception {
assertDependencyByMetaInf("StAX", "1.0.1");
}
private void assertDependencyByMetaInf(final String specTitle,
final String expectedSpecVersion) throws IOException {
final ClassLoader cl = this.getClass().getClassLoader();
final String resourcePath = "META-INF/MANIFEST.MF";
final Enumeration<URL> resources = cl.getResources(resourcePath);
boolean found = false;
while (resources.hasMoreElements()) {
final URL url = resources.nextElement();
final InputStream metaInfStream = url.openStream();
final Properties metaInf = new Properties();
metaInf.load(metaInfStream);
final String metaInfSpecTitle =
metaInf.getProperty("Specification-Title");
if (!specTitle.equals(metaInfSpecTitle)) {
continue;
}
final String specVersion =
metaInf.getProperty("Specification-Version");
assertEquals("version mismatch for " + specTitle,
expectedSpecVersion, specVersion);
found = true;
}
assertTrue("missing dependency: " + specTitle, found);
}
Following the advice from palacsint, here is another approach: Count how often a class is on the classpath and print the URLs if there is more than one.
private void assertOnceOnClassPath( String resourcePath ) throws IOException {
ClassLoader cl = getClass().getClassLoader();
Enumeration<URL> resources = cl.getResources( resourcePath );
List<URL> urls = new ArrayList<URL>();
while( resources.hasMoreElements() ) {
URL url = resources.nextElement();
urls.add( url );
}
if( urls.size() != 1 ) {
fail( "Expected exactly 1 item:\n" + StringUtils.join( urls, "\n" ) );
}
}
精彩评论