开发者

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 used org.apache.commons:commons-io

  • The wrong version of a dependency was used

  • stax uses the versions 1.0-2 and 1.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" ) );
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜