Search code examples
testngpax-exam

Pax-Exam issue with TestNG Integration


I tried to integrate pax-exam plugin with testng and ended up getting the following error. However it was working fine with the junit.

[org.ops4j.pax.exam.spi.intern.DefaultTestAddress] : NEW ADDRESS= PaxExam-90b1718e-7414-486a-8ae2-b5628e4b7a67 parent=[TestAddress:PaxExam-ea9b0dd3-b693-4efb-8003-7f6b92b05f99 root:PaxExam-ea9b0dd3-b693-4efb-8003-7f6b92b05f99] root=[TestAddress:PaxExam-ea9b0dd3-b693-4efb-8003-7f6b92b05f99 root:PaxExam-ea9b0dd3-b693-4efb-8003-7f6b92b05f99] args=[Ljava.lang.Object;@4f063c0a
[org.ops4j.pax.exam.spi.intern.DefaultTestAddress] : NEW ADDRESS= PaxExam-652d3b11-ab7c-49d0-bcba-f9d56c9210ee parent=[TestAddress:PaxExam-806e1a66-76ff-44cf-90d9-ff26b658b855 root:PaxExam-806e1a66-76ff-44cf-90d9-ff26b658b855] root=[TestAddress:PaxExam-806e1a66-76ff-44cf-90d9-ff26b658b855 root:PaxExam-806e1a66-76ff-44cf-90d9-ff26b658b855] args=[Ljava.lang.Object;@1e6d1014
org.apache.maven.surefire.util.SurefireReflectionException: java.lang.reflect.InvocationTargetException; nested exception is java.lang.reflect.InvocationTargetException: null
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:103)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:74)
Caused by: java.lang.NoSuchMethodError: org.testng.internal.MethodInstance.<init>(Lorg/testng/ITestNGMethod;)V
    at org.ops4j.pax.exam.testng.listener.PaxExam.intercept(PaxExam.java:503)
    at org.testng.TestRunner.createParallelWorkers(TestRunner.java:995)
    at org.testng.TestRunner.privateRun(TestRunner.java:747)
    at org.testng.TestRunner.run(TestRunner.java:608)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1158)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1083)
    at org.testng.TestNG.run(TestNG.java:999)
    at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:76)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:112)
    at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:115)
    ... 9 more

Any idea what went wrong here?.

Following is my sample test code. I think this is the basic test-case we can write.

import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerClass;
import org.ops4j.pax.exam.testng.listener.PaxExam;
import org.osgi.framework.BundleContext;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

import javax.inject.Inject;

import static org.testng.Assert.assertNotNull;
import static org.ops4j.pax.exam.CoreOptions.*;


@Listeners(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
public class SampleTest {

    @Inject
    BundleContext bundleContext;

    @Configuration
    public Option[] config() {

        return options(
                mavenBundle().artifactId("testng").groupId("org.testng").versionAsInProject()
        );
    }

    @Test
    public void testBundleContextStatus() {
        assertNotNull(bundleContext, "Bundle Context is null");
    }
}

Here is the dependencies I've used.

<dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam</artifactId>
            <version>${exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-container-native</artifactId>
            <version>${exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-testng</artifactId>
            <version>${exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-link-mvn</artifactId>
            <version>${exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.url</groupId>
            <artifactId>pax-url-aether</artifactId>
            <version>${url.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.api.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ow2.spec.ee</groupId>
            <artifactId>ow2-jta-1.1-spec</artifactId>
            <version>${ow2.jta.spec.version}</version>
            <scope>test</scope>
        </dependency>

After changing the testng depenedncy version to 6.3.1 it worked correctly. But for latest released version which is 6.9.6 issue is there.


Solution

  • The latest edit to the question contains the answer. Pax Exam 4.6.0 was compiled with TestNG 6.8.17, and apparently there has been an incompatible API change in TestNG 6.9.x.

    Pax Exam directly uses some internal classes of TestNG for lack of a better alternative.

    You're better off using Pax Exam with JUnit in general. JUnit is better integrated and has a lot more test coverage and usage in OPS4J and other downstream projects.