是否可以创建一个使用EasyMock实现多个接口的模拟对象?

Dan*_*nov 42 java unit-testing rhino-mocks easymock mocking

是否可以创建一个使用EasyMock实现多个接口的模拟对象?

例如,界面Foo和界面Closeable

在Rhino Mocks中,您可以在创建模拟对象时提供多个接口,但EasyMock的createMock()方法只需要一种类型.

难道possbile与EasyMock的实现这一点,而不诉诸创建扩展双方暂时接口的后退FooCloseable,然后嘲讽吗?

Tho*_*our 72

虽然我从根本上同意尼克霍尔特的回答,但我想我应该指出,mockito允许通过以下调用做你所要求的事情:

Foo mock = Mockito.mock(Foo.class, withSettings().extraInterfaces(Bar.class));
Run Code Online (Sandbox Code Playgroud)

显然你将不得不使用强制转换:(Bar)mock当你需要使用模拟作为一个,Bar但该投射不会抛出ClassCastException

这是一个更完整的例子,虽然完全荒谬:

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) {
        }
    }
Run Code Online (Sandbox Code Playgroud)


ext*_*eon 14

你考虑过这样的事情:

interface Bar extends Foo, Closeable {
}
Run Code Online (Sandbox Code Playgroud)

然后模拟界面栏?


Nic*_*olt 10

EasyMock不支持这一点,因此你会遇到临时接口的后备问题.

顺便说一句,我闻到了代码WIFF一点点-应的方法真的治疗对象为2分不同的东西,在FooCloseable在这种情况下接口?

这对我来说意味着该方法正在执行多个操作,而我怀疑其中一个操作是"关闭" Closeable,那么调用代码是否更有意义来决定是否需要"关闭"?

以这种方式构造代码使得'open'和'close'保持在同一个try ... finally块中,并且IMHO使代码更具可读性,更不用说更通用的方法,并允许您传递仅实现的对象Foo.

  • 我同意这一点,但要扩展:如果你使用依赖注入,并且你的类需要一个Foo和一个Closable,你应该有两个单独的setter.如果你选择为这两个对象注入相同的对象,那么很好,但我认为被测试的类不需要知道它们是同一个对象 - 它应该将Foo视为Foo而将Closeable视为一个封闭的 (4认同)
  • @NickHolt:我不会完全同意你的看法。考虑一下当您有一个接口“ Person”仅具有getter(“ getFirstName()”,“ getAddress()”,...)和接口“ ModifiablePerson”仅具有setter(“ setFirstName()”,“ setAddress()`,...)。现在,您要测试一个采用`Person`的SUT,但是要检查是否传递了对象`instanceof ModifiablePerson`并基于此进行了某些操作。“ Closeable”也是一个很好的例子:如果对象提供了“扩展”功能(由instanceof`明确检查并利用了),那有什么不好呢? (2认同)

Nic*_*tto 5

投票最多的答案的替代方案仍基于Mockito,但带有注释。您可以extraInterfaces直接从Mock注释中设置,如下所示:

@RunWith(MockitoJUnitRunner.class)
public class MyTest {
    @Mock(extraInterfaces = Closeable.class)
    private Foo foo;
    ...
}
Run Code Online (Sandbox Code Playgroud)

NB: extraInterfaces是类型,Class<?>[]因此您可以根据需要指定多个接口。

如果您需要模拟额外接口的方法调用,则需要进行模拟转换。例如,假设我想在模拟IOException时调用,则相应的代码将是:close()foo

Mockito.doThrow(IOException.class).when((Closeable) foo).close();
Run Code Online (Sandbox Code Playgroud)