Java 是否可以创建一个使用 EasyMock 实现多个接口的模拟对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1170708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to create a mock object that implements multiple interfaces with EasyMock?
提问by Daniel Fortunov
Is it possible to create a mock object that implements several interfaces with EasyMock?
是否可以创建一个使用 EasyMock 实现多个接口的模拟对象?
For example, interface Foo
and interface Closeable
?
例如,接口Foo
和接口Closeable
?
In Rhino Mocks you can provide multiple interfaces when creating a mock object, but EasyMock's createMock()
method only takes one type.
在 Rhino Mocks 中你可以在创建一个 mock 对象时提供多个接口,但是 EasyMock 的createMock()
方法只接受一种类型。
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?
是否可以使用 EasyMock 来实现这一点,而不诉诸于创建一个扩展了Foo
和的临时接口,Closeable
然后模拟它?
采纳答案by Nick Holt
EasyMock doesn't support this so you're stuck with fallback of the temporary interface.
EasyMock 不支持此功能,因此您会遇到临时接口的回退问题。
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?
顺便说一句,我闻到了代码WIFF一点点-应的方法真的治疗对象为2分不同的东西,在Foo
和Closeable
在这种情况下接口?
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?
这对我来说意味着该方法正在执行多个操作,虽然我怀疑其中一个操作是“关闭” Closeable
,但调用代码决定是否需要“关闭”不是更有意义吗?
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
.
以这种方式构建代码可以将“打开”和“关闭”保持在同try ... finally
一块中,恕我直言,使代码更具可读性,更不用说更通用的方法,并允许您传递仅实现Foo
.
回答by extraneon
have you considered something like:
你有没有考虑过这样的事情:
interface Bar extends Foo, Closeable {
}
and then mock interface Bar?
然后模拟界面吧?
回答by Rogério
To the best of my knowledge, the only mocking tool for Java that has explicit support for mocking multiple interfaces is JMockit. (My inspiration for adding this feature came from Moq and Rhino Mocks, which are .NET tools.)
据我所知,唯一明确支持模拟多个接口的 Java 模拟工具是JMockit。(我添加此功能的灵感来自 Moq 和 Rhino Mocks,它们是 .NET 工具。)
An example (from the mockit.ExpectationsUsingMockedTest
JUnit 4 test class):
一个例子(来自mockit.ExpectationsUsingMockedTest
JUnit 4 测试类):
@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();
}
Dependency
and Runnable
are interfaces. The doSomething
method belongs to the first, and run
to the second.
Dependency
并且Runnable
是接口。该doSomething
方法属于第一种,也属于run
第二种。
回答by Thomas Dufour
Although I fundamentally agree with Nick Holt's answer, I thought I should point out that mockitoallows to do what you ask with the following call :
尽管我从根本上同意 Nick Holt 的回答,但我想我应该指出,mockito允许通过以下调用执行您的要求:
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
显然,您必须使用演员表:(Bar)mock
当您需要将模拟用作 aBar
但该演员表不会抛出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) {
}
}
回答by Haroldo_OK
Another way to solve this problem is to use a CGLib mixin:
解决此问题的另一种方法是使用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...
这是否是一个好主意,这有待讨论……
回答by Nicolas Filotto
An alternative of the most voted answerstill based on Mockitobut with annotations. You can set the extraInterfaces
directly from the Mock
annotation as next:
投票最多的答案的替代方案仍然基于Mockito,但带有注释。您可以extraInterfaces
直接从Mock
注释中设置 ,如下所示:
@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.
注意:extraInterfaces
是类型,Class<?>[]
因此您可以根据需要指定多个接口。
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:
如果您需要模拟额外接口的方法调用,您将需要转换您的模拟。例如,假设我想IOException
在调用close()
我的 mock时抛出 an foo
,则相应的代码将是:
Mockito.doThrow(IOException.class).when((Closeable) foo).close();