Use Mockito with OpenEJB


Maybe Mockito sounds today an old school way to write a test since Arquillian is out but it keeps some benefit in some complicated cases.

That’s why in last days OpenEJB was integrated with Mockito.

There are currently two integrations:

  • ApplicationComposer
  • OpenEJB embedded arquillian adapter

Why TomEE arquillian adapter was not integrated is mainly because in its current version it is not so easy to be sure of the Arquillian injection order in test instance. So the mock (needs to be the first enricher) and the CDI enricher (for instance) can be called in the bad order (but don’t worry Arquillian team is aware of it and works on it).

OpenEJB, Mockito & Arquillian

To use Mockito with OpenEJB arquillian adapter you’ll simply need to add mockito-core as dependency in your application. Then you’ll be able to inject mocks in your test class using the Mockito annotation @Mock.

To use it to mock CDI beans you’ll need to respect some minor rules to avoid some headaches:

  • a mocked injection needed at deploy time can’t work (@Singleton @Startup injection are not compatible)
  • To add the mock in CDI context you’ll “@Produces” it but this producer should be called before the injection need. Since the injection will be needed when your test instance will get injection use a static producer field to be sure it will be present for CDI injections (= before the test instance is created).

Here a sample:

@RunWith(Arquillian.class)
public class ArquillianAndMockitoTest {
    @Inject
    private AFooBean bean;
    @Mock @Produces
    private static AnInterface mock;

    @Deployment
    public static JavaArchive archive() {
        return ShrinkWrap.create(JavaArchive.class, ArquillianAndMockitoTest.class.getSimpleName().concat(".jar"))
                .addClasses(AnInterface.class, AFooBean.class)
                .addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));
    }

    @Test
    public void mockWorks() {
        assertNotNull(bean);
        assertNotNull(mock);
        assertNotNull(bean.get());
    }

    public static interface AnInterface {}

    public static class AFooBean {
        @Inject
        private AnInterface mock;

        public AnInterface get() {
            return mock;
        }
    }
}

ApplicationComposer & Mockito

This integration is probably better in more cases (but doesn’t use Arquillian).

The idea was to add to the ApplicationComposer a new annotation @MockInjector to be able to specify a FallbackPropertyInjector. This class is used to retrieve from an injection point the desired value if noone was found by the container (typically a missing class in the deployer application). Then implementing a mock injector specific to mockito we added the support of mock injection like we saw just before with Arquillian and then we were able to add these mocks in CDI context through a CDI extension (ApplicationComposer lifecycle is different from the Arquillian one so it was possible here).

This way your mocks are CDI beans with no producers or weird lifecycle issues :).

Here a little sample:

@RunWith(ApplicationComposer.class)
public class MockitoAndAppComposerTest {
    @EJB
    private Facade facade;

    @Mock
    private Hello mock;

    @Mock(name = "named")
    private Hello named;

    @MockInjector
    public Class<?> mockitoInjector() {
        return MockitoInjector.class;
    }

    @Module
    public Class<?>[] classes() {
        return new Class<?>[] { Hello.class, Facade.class };
    }

    @Test
    public void testDefault() {
        // play with mocks
        when(mock.hi())
            .thenReturn("openejb-mockito");
        when(mock.id())
                .thenReturn(12345);

        // test
        assertEquals("openejb-mockito", facade.hello());
    }

    @Test
    public void testName() {
        // play with mocks
        when(named.hi())
                .thenReturn("named");

        // test
        assertEquals("named", facade.name());
    }
}

You can already test it adding Apache snapshot maven repository to your pom with the dependecy on openejb-mockito:

<repository>
  <id>apache-snapshots</id>
  <name>Apache Snapshots Repository</name>
  <url>http://repository.apache.org/content/groups/snapshots-group</url>
</repository>

 

<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-mockito</artifactId>
<version>4.1.0-SNAPSHOT</version>
</dependency>
Advertisements

9 thoughts on “Use Mockito with OpenEJB

  1. Runar Kristiansen Halse

    Hi! I’ve been creating some tests using the applicationComposer and mockito lately, and have run into a problem. I’m using it to test a jax-rs service, injecting mocks into it and such. To perform a complete test of the service however, I need to include testing of some exception-mappers annotated with @Provider. I cannot seem to get this to work. It appears you might have the knowledge to help me, so I was hoping you could take a brief look at my unanswered question on stackoverflow: http://stackoverflow.com/questions/13087255/openejb-rest-integration-tests-with-exception-mappers

    Thanks!

    Reply
      1. Runar Kristiansen Halse

        do you have any other suggestions? I also tried to add the exception mapper to the managed classes of a new Beans instance, that was added to teh EjbModule. Am I completely lost here?

      2. Runar Kristiansen Halse

        Thanks for all your help, but we cannot get the tests to include the exception mappers. They work as expected when deployed to our websphere server. We have decided not spend any more time on writing tests for this. Thanks though!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s