ops4j / org.ops4j.pax.exam2

Pax Exam is a testing framework for OSGi
https://ops4j1.jira.com/wiki/spaces/PAXEXAM4/
Apache License 2.0
84 stars 100 forks source link

jMock not working off the shelf [PAXEXAM-343] #476

Closed ops4j-issues closed 3 weeks ago

ops4j-issues commented 12 years ago

Caspar MacRae created PAXEXAM-343

Hi, there's a few issues with getting jMock to work in Pax Exam (2.3.0).

Annoyingly jUnit's default distribution includes some (but not all) of the hamcrest library and this is the one being used in PaxExam (org.junit/com.springsource.org.junit/4.9.0) which doesn't contain org.hamcrest.TypeSafeMatcher, required by jMock.

This is easily worked around by replacing the JUnitBundlesOption with, e.g. wrap:mvn:junit/junit-dep/4.10 (junit-dep doesn't include any of hamcrest).

Then hamcrest has a split package org.hamcrest between hamcrest-core and hamcrest-library (version 1.3.RC2), which can be worked around by not exporting this package from the hamcrest-library (where it just contains a static builder/helper). Hamcrest also requires DynamicImport-Package to be specified.

The code below works, but if you replace customJunitBundles() with junitBundles() then it will fail. Not sure what's the best solution to get this working out of the box - perhaps make jmockBundles and junitBundles options mutually exclusive and include all the junit and hamcrest specifics in the jmockBundles option?

JMockIntegrationTest.java


import static org.junit.Assert.*;
import static org.ops4j.pax.exam.Constants.START_LEVEL_SYSTEM_BUNDLES;
import static org.ops4j.pax.exam.CoreOptions.*;
import static org.ops4j.pax.exam.OptionUtils.*;
import static org.ops4j.pax.exam.spi.PaxExamRuntime.*;

import java.io.IOException;

import javax.inject.Inject;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Info;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.TimeoutException;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.ExamReactorStrategy;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.ops4j.pax.exam.options.MavenArtifactUrlReference;
import org.ops4j.pax.exam.options.WrappedUrlProvisionOption;
import org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactorFactory;
import org.osgi.framework.BundleContext;

/**
 * @author caspar
 */
@RunWith(JUnit4TestRunner.class)
@ExamReactorStrategy(AllConfinedStagedReactorFactory.class)
public class JMockIntegrationTest {

    private static final String VERSION_JUNIT_DEP = "4.10";
    private static final String VERSION_HAMCREST = "1.3.RC2";
    private static final String VERSION_JMOCK = "2.5.1";

    @Inject
    BundleContext context;

    public static void main(String[] args) throws TimeoutException, IOException {
        createContainer(
                createTestSystem(
                        combine(
                                new JMockIntegrationTest().config(), 

                                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.gogo.runtime").version("0.10.0"),
                                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.gogo.shell").version("0.10.0"),
                                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.gogo.command").version("0.10.0")
                        )
                )).start();
    }

    @Configuration
    public Option[] config()
    {
        return new Option[]{
//              junitBundles(),
                customJunitBundles(),
                hamcrestBundle(),
                jmock2Bundle()
        };
    }

    public static Option customJunitBundles()
    {
        return composite(
                wrappedBundle(maven().groupId("junit").artifactId("junit-dep").version(VERSION_JUNIT_DEP)).startLevel(START_LEVEL_SYSTEM_BUNDLES),
                systemProperty( "pax.exam.invoker" ).value( "junit" ),            
                mavenBundle("org.ops4j.pax.exam", "pax-exam-invoker-junit", Info.getPaxExamVersion()));
    }

    public static Option hamcrestBundle()
    {
        return composite(
                addDynamicImport(maven().groupId("org.hamcrest").artifactId("hamcrest-core").version(VERSION_HAMCREST)),
                addDynamicImport(maven().groupId("org.hamcrest").artifactId("hamcrest-library").version(VERSION_HAMCREST)).exports(
                            "org.hamcrest.beans", "org.hamcrest.collection", "org.hamcrest.number", "org.hamcrest.object",
                            "org.hamcrest.text", "org.hamcrest.xml")
            );
    }

    public static Option jmock2Bundle()
    {
        return wrappedBundle(
                maven().groupId("org.jmock").artifactId("jmock").version(VERSION_JMOCK)
        ).noUpdate();

    }

    private static WrappedUrlProvisionOption addDynamicImport(MavenArtifactUrlReference reference)
    {
        return wrappedBundle(reference).instructions("DynamicImport-Package=*");
    }

    public interface Person {
        public String getName();        
    }

    @Test
    public void jMockeryOfExternalDep()
    {
        final Mockery mockery = new Mockery();
        assertNotNull(mockery);
        final Person p = mockery.mock(Person.class);
        mockery.checking(new Expectations() {{
            allowing(p).getName(); will(returnValue("derek"));
        }});
        assertEquals("derek", p.getName());
        mockery.assertIsSatisfied();
    }
}

Affects: 2.3.0.M1, 2.3.0 Votes: 0, Watches: 1

ops4j-issues commented 12 years ago

Harald Wellmann commented

We had a similar issue with Mockito and JUnit, see PAXEXAM-274 .

I'm afraid there is no quick solution.

All these xxxBundles() options are hard to maintain and are likely to be deprecated.
Pax Exam 2.4.0 will let the user override all provisioning defaults, including Exam's own bundles.

Regarding JUnit and Hamcrest, it's really a nuisance that JUnit is not osgified by default, and the SpringSource bundle we're currently using is also flawed, it exports the org.hamcrest packages with an incorrect version.

We might solve this by properly osgifying JUnit on our own.

Anyway, thanks for posting your workaround!