简体   繁体   中英

Why does Maven Surefire 3 fail to run my Cucumber test in Jenkins with Docker?

I have a Java project with some Cucumber tests and some regular JUnit tests, managed by Maven.

I want to run the tests in Jenkins, using Docker, so I wrote this Jenkinsfile :

pipeline {
    agent {
        docker {
            image 'maven:3.6.1'
        }
    }
    stages {
        stage('build') {
            steps {
                sh 'mvn clean verify -Dmaven.test.failure.ignore=true'
            }
            post {
                success {
                    junit 'target/surefire-reports/**/*.xml'
                }
            }
        }
    }
}

When I run the build, the regular tests pass but the Cucumber tests fail with:

Error Message

URI has a query component

Stacktrace

java.lang.IllegalArgumentException: URI has a query component

It's not until I disable trimStackTrace for maven-surefire-plugin that I also get the details:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <trimStackTrace>false</trimStackTrace>
    </configuration>
</plugin>
java.lang.IllegalArgumentException: URI has a query component
    at java.base/java.io.File.<init>(File.java:427)
    at cucumber.runtime.io.ZipResourceIterator.<init>(ZipResourceIterator.java:22)
    at cucumber.runtime.io.ZipResourceIteratorFactory.createIterator(ZipResourceIteratorFactory.java:24)
    at cucumber.runtime.io.ZipThenFileResourceIteratorFactory.createIterator(ZipThenFileResourceIteratorFactory.java:22)
    at cucumber.runtime.io.DelegatingResourceIteratorFactory.createIterator(DelegatingResourceIteratorFactory.java:49)
    at cucumber.runtime.io.ClasspathResourceIterable.iterator(ClasspathResourceIterable.java:35)
    at cucumber.runtime.io.ResourceLoaderClassFinder.getDescendants(ResourceLoaderClassFinder.java:25)
    at cucumber.runtime.Reflections.instantiateSubclasses(Reflections.java:34)
    at cucumber.runtime.BackendModuleBackendSupplier.loadBackends(BackendModuleBackendSupplier.java:52)
    at cucumber.runtime.BackendModuleBackendSupplier.get(BackendModuleBackendSupplier.java:39)
    at cucumber.runner.ThreadLocalRunnerSupplier.createRunner(ThreadLocalRunnerSupplier.java:42)
    at cucumber.runner.ThreadLocalRunnerSupplier.access$000(ThreadLocalRunnerSupplier.java:13)
    at cucumber.runner.ThreadLocalRunnerSupplier$1.initialValue(ThreadLocalRunnerSupplier.java:22)
    at cucumber.runner.ThreadLocalRunnerSupplier$1.initialValue(ThreadLocalRunnerSupplier.java:19)
    at java.base/java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:195)
    at java.base/java.lang.ThreadLocal.get(ThreadLocal.java:172)
    at cucumber.runner.ThreadLocalRunnerSupplier.get(ThreadLocalRunnerSupplier.java:38)
    at cucumber.api.junit.Cucumber$RunCucumber.evaluate(Cucumber.java:146)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)

This is quite puzzling because:

  • when running mvn verify locally, it works
  • when using agent any in the Dockerfile , instead of the maven Docker image, it works
  • when using maven-surefire-plugin version 2.22.2 instead of 3.0.0-M3 , it works

I logged in as Jenkins and looked in the workspace:

$ sudo su - jenkins

$ ls /var/lib/jenkins/workspace/question-mark-dir_master
'?'   Jenkinsfile   LICENSE   pom.xml   README.md   src   target

There's a question mark ( ? ) directory in there, and it contains the .m2 directory, with all the artifacts needed by the project. I suspect this could be the cause of the exception, because then there are question marks in the classpath, and question marks are the ones who introduce the query component of URIs.

For the moment I can downgrade to maven-surefire-plugin version 2.22.2 as a workaround. But what is the actual problem here?

  • Could it be a bug in the new maven-surefire-plugin ? Judging by the stack trace I wouldn't bet on that.
  • Is it a problem in Jenkins or in the Maven docker image (which one?), that causes a directory to have such an unfortunate name?
  • Am I doing something wrong?

If you want to try this out, I have a MVCE . In my local Jenkins installation, I created a new project of type "Multibranch Pipeline" and in "Branch Sources" I added as the git project repository my local git project. No other changes.

屏幕截图

By combining TYY's comment to the question and the documentation of the maven docker image , I was able to configure the Jenkinsfile in a way that avoids creating a question mark directory.

We need to inform Maven of the user's home directory, and map that to a directory outside the container.

pipeline {
    agent {
        docker {
            image 'maven:3.6.1'
            args '-v /var/lib/jenkins:/usr/src/mymaven -w /usr/src/mymaven'
        }
    }
    stages {
        stage('build') {
            steps {
                sh 'MAVEN_OPTS="-Duser.home=/usr/src/mymaven" mvn clean verify -Dmaven.test.failure.ignore=true'
            }
            // ...
        }
    }
}
  • -v /var/lib/jenkins:/usr/src/mymaven maps the /var/lib/jenkins directory on the host to the /usr/src/mymaven directory inside the container
  • -w /usr/src/mymaven sets the working directory inside the container
  • MAVEN_OPTS="-Duser.home=/usr/src/mymaven" sets the user.home Java property for Maven

Proof that it works, on a branch of the MCVE.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM