Is it possible to create a mock object that implements multiple interfaces with EasyMock?

JavaUnit TestingMockingRhino MocksEasymock

Java Problem Overview


Is it possible to create a mock object that implements several interfaces with EasyMock?

For example, interface Foo and interface Closeable?

In Rhino Mocks you can provide multiple interfaces when creating a mock object, but EasyMock's createMock() method only takes one type.

Is it possbile to achieve this with EasyMock, without resorting to the fallback of creating a temporary interface that extends both Foo and Closeable, and then mocking that?

Java Solutions


Solution 1 - Java

Although I fundamentally agree with Nick Holt's answer, I thought I should point out that mockito allows to do what you ask with the following call :

Foo mock = Mockito.mock(Foo.class, withSettings().extraInterfaces(Bar.class));

Obviously you'll have to use the cast: (Bar)mock when you need to use the mock as a Bar but that cast will not throw ClassCastException

Here is an example that is a bit more complete, albeit totally absurd:

import static org.junit.Assert.fail;
import org.junit.Test;
import static org.mockito.Mockito.*;
import org.mockito.Mockito;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import org.hamcrest.Matchers;

import java.util.Iterator;


public class NonsensicalTest {


	@Test
	public void testRunnableIterator() {
        // This test passes.

		final Runnable runnable = 
                    mock(Runnable.class, withSettings().extraInterfaces(Iterator.class));
		final Iterator iterator = (Iterator) runnable;
		when(iterator.next()).thenReturn("a", 2);
		doThrow(new IllegalStateException()).when(runnable).run();

		assertThat(iterator.next(), is(Matchers.<Object>equalTo("a")));

		try {
			runnable.run();
			fail();
		}
		catch (IllegalStateException e) {
		}
	}

Solution 2 - Java

have you considered something like:

interface Bar extends Foo, Closeable {
}

and then mock interface Bar?

Solution 3 - Java

EasyMock doesn't support this so you're stuck with fallback of the temporary interface.

As an aside, I smell a little bit of a code wiff - should a method really be treating an object as 2 different things, the Foo and Closeable interface in this case?

This implies to me that the method is performing multiple operations and while I suspect one of those operations is to 'close' the Closeable, wouldn't it make more sense for the calling code to decide whether or not the 'close' is required?

Structuring the code this way keeps the 'open' and 'close' in the same try ... finally block and IMHO makes the code more readable not to mention the method more general and allows you to pass objects that only implement Foo.

Solution 4 - Java

An alternative of the most voted answer still based on Mockito but with annotations. You can set the extraInterfaces directly from the Mock annotation as next:

@RunWith(MockitoJUnitRunner.class)
public class MyTest {
    @Mock(extraInterfaces = Closeable.class)
    private Foo foo;
    ...
}

NB: extraInterfaces is of type Class<?>[] so you can specify several interfaces if needed.

If you need to mock method calls of the extra interfaces you will need to cast your mock. For example let's say that I want to throw an IOException when I call close() on my mock foo, the corresponding code would then be:

Mockito.doThrow(IOException.class).when((Closeable) foo).close();

Solution 5 - Java

To the best of my knowledge, the only mocking tool for Java that has explicit support for mocking multiple interfaces is https://jmockit.dev.java.net">JMockit</a>;. (My inspiration for adding this feature came from Moq and Rhino Mocks, which are .NET tools.)

An example (from the mockit.ExpectationsUsingMockedTest JUnit 4 test class):


@Test
public <M extends Dependency & Runnable> void mockParameterWithTwoInterfaces(final M mock)
{
new Expectations()
{
{
mock.doSomething(true); returns("");
mock.run();
}
};




assertEquals("", mock.doSomething(true));
mock.run();
}

assertEquals("", mock.doSomething(true)); mock.run(); }

Dependency and Runnable are interfaces. The doSomething method belongs to the first, and run to the second.

Solution 6 - Java

Another way to solve this problem is to use a CGLib mixin:

final Interface1 interface1 = mockery.mock(Interface1.class);
final Interface2 interface2 = mockery.mock(Interface2.class);

service.setDependence(Mixin.create(new Object[]{ interface1, interface2 }));

mockery.checking(new Expectations(){{
	oneOf(interface1).doSomething();
	oneOf(interface2).doNothing();
}});

service.execute();

Whether or not this is a good idea, it's something up to discussion...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel FortunovView Question on Stackoverflow
Solution 1 - JavaThomas DufourView Answer on Stackoverflow
Solution 2 - JavaextraneonView Answer on Stackoverflow
Solution 3 - JavaNick HoltView Answer on Stackoverflow
Solution 4 - JavaNicolas FilottoView Answer on Stackoverflow
Solution 5 - JavaRogérioView Answer on Stackoverflow
Solution 6 - JavaHaroldo_OKView Answer on Stackoverflow