首页 文章

如何使用mockito模拟void方法

提问于
浏览
758

如何用void返回类型模拟方法?

我实现了一个观察者模式,但我不能用Mockito模仿它,因为我不知道如何 .

我试图在互联网上找到一个例子,但没有成功 .

我的 class 看起来像

public class World {

    List<Listener> listeners;

    void addListener(Listener item) {
        listeners.add(item);
    }

    void doAction(Action goal,Object obj) {
        setState("i received");
        goal.doAction(obj);
        setState("i finished");
    }

    private string state;
    //setter getter state
} 

public class WorldTest implements Listener {

    @Test public void word{
    World  w= mock(World.class);
    w.addListener(this);
    ...
    ...

    }
}

interface Listener {
    void doAction();
}

系统不会被模拟触发 . =(我想显示上面提到的系统状态 . 并根据它们进行断言 .

10 回答

  • 54

    @ashley:适用于我的公共类AssetChangeListenerImpl扩展
    AbstractAssetChangeListener实现AssetChangeListener {

    @覆盖
    public void onChangeEvent(final EventMessage message)抛出EventHubClientException {
    执行(消息);
    }
    }
    }

    公共类AbstractAssetChangeListener {
    protected void execute(final EventMessage message)抛出EventHubClientException {
    executor.execute(new PublishTask(getClient(),message));
    @RunWith(MockitoJUnitRunner.class)公共类AssetChangeListenerTest扩展AbstractAssetChangeListenerTest {

    public void testExecute()抛出EventHubClientException {
    EventMessage message = createEventMesage(EventType.CREATE);
    assetChangeListener.execute(消息);
    verify(assetChangeListener,times(1)) . execute(message);
    }}

  • 51

    添加到@sateesh所说的,当你只想模拟一个void方法以防止测试调用它时,你可以这样使用 Spy

    World world = new World();
    World spy = Mockito.spy(world);
    Mockito.doNothing().when(spy).methodToMock();
    

    如果要运行测试,请确保在 spy 对象上调用test中的方法,而不是在 world 对象上调用 . 例如:

    assertEquals(0,spy.methodToTestThatShouldReturnZero());
    
  • 12

    我想我已经找到了一个更简单的答案,只为一个方法调用真正的方法(即使它有一个void返回)你可以这样做:

    Mockito.doCallRealMethod().when(<objectInstance>).<method>();
    <objectInstance>.<method>();
    

    或者,您可以为该类的所有方法调用实际方法,执行以下操作:

    <Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);
    
  • 23

    首先:你应该总是导入mockito static,这样代码将更具可读性(更直观):

    import static org.mockito.Mockito.*;
    

    对于部分嘲笑,仍然保持原有功能的其余mockito提供“ Spy ” .

    您可以按如下方式使用它:

    private World world = spy(World.class);
    

    要消除执行方法,您可以使用以下内容:

    doNothing().when(someObject).someMethod(anyObject());
    

    为方法提供一些自定义行为使用“when”与“thenReturn”:

    doReturn("something").when(this.world).someMethod(anyObject());
    

    有关更多示例,请在doc中找到mockito示例 .

  • 972

    我认为你的问题是由于你的测试结构 . 我发现很难将mocking与在测试类中实现接口的传统方法混合在一起(正如你在这里所做的那样) .

    如果您将侦听器实现为Mock,则可以验证交互 .

    Listener listener = mock(Listener.class);
    w.addListener(listener);
    world.doAction(..);
    verify(listener).doAction();
    

    这应该让你满意,“世界”正在做正确的事情 .

  • 5

    添加另一个答案(没有双关语)...

    你需要调用doAnswer方法,如果你想's. However, you don' t想要使用 Spy 's. However, you don' t必须要自己滚动Answer . 有几个默认实现 . 值得注意的是,CallsRealMethods .

    在实践中,它看起来像这样:

    doAnswer(new CallsRealMethods()).when(mock)
            .voidMethod(any(SomeParamClass.class));
    

    要么:

    doAnswer(Answers.CALLS_REAL_METHODS.get()).when(mock)
            .voidMethod(any(SomeParamClass.class));
    
  • 0

    看看Mockito API docs . 如链接文档所述(第12点),您可以使用Mockito框架中的任何 doThrow()doAnswer()doNothing()doReturn() 方法系列来模拟void方法 .

    例如,

    Mockito.doThrow(new Exception()).when(instance).methodName();
    

    或者如果你想将它与后续行为相结合,

    Mockito.doThrow(new Exception()).doNothing().when(instance).methodName();
    

    假设你正在嘲笑下面的类World中的setter setState(String s) ,代码使用 doAnswer 方法来模拟 setState .

    World  mockWorld = mock(World.class); 
    doAnswer(new Answer<Void>() {
        public Void answer(InvocationOnMock invocation) {
          Object[] args = invocation.getArguments();
          System.out.println("called with arguments: " + Arrays.toString(args));
          return null;
        }
    }).when(mockWorld).setState(anyString());
    
  • 5

    How to mock void methods with mockito - there are two options:

    • doAnswer - 如果我们希望我们的模拟void方法做某事(尽管是无效的模拟行为) .

    • doThrow - 如果要从模拟的void方法中抛出异常,则会有 Mockito.doThrow() .

    以下是如何使用它的示例(不是理想的用例,只是想说明基本用法) .

    @Test
    public void testUpdate() {
    
        doAnswer(new Answer<Void>() {
    
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Object[] arguments = invocation.getArguments();
                if (arguments != null && arguments.length > 1 && arguments[0] != null && arguments[1] != null) {
    
                    Customer customer = (Customer) arguments[0];
                    String email = (String) arguments[1];
                    customer.setEmail(email);
    
                }
                return null;
            }
        }).when(daoMock).updateEmail(any(Customer.class), any(String.class));
    
        // calling the method under test
        Customer customer = service.changeEmail("old@test.com", "new@test.com");
    
        //some asserts
        assertThat(customer, is(notNullValue()));
        assertThat(customer.getEmail(), is(equalTo("new@test.com")));
    
    }
    
    @Test(expected = RuntimeException.class)
    public void testUpdate_throwsException() {
    
        doThrow(RuntimeException.class).when(daoMock).updateEmail(any(Customer.class), any(String.class));
    
        // calling the method under test
        Customer customer = service.changeEmail("old@test.com", "new@test.com");
    
    }
    }
    

    您可以在我的帖子中找到有关如何使用Mockito的 mocktest void 方法的更多详细信息How to mock with Mockito (A comprehensive guide with examples)

  • 18

    在Java 8中,假设您有 org.mockito.Mockito.doAnswer 的静态导入,则可以使其更清晰:

    doAnswer(i -> {
      // Do stuff with i.getArguments() here
      return null;
    }).when(*mock*).*method*(*methodArguments*);
    

    return null; 很重要,如果没有它,编译将失败并出现一些相当模糊的错误,因为它无法为 doAnswer 找到合适的覆盖 .

    例如,只需立即执行 Runnable 传递给 execute()ExecutorService 可以使用以下方法实现:

    doAnswer(i -> {
      ((Runnable) i.getArguments()[0]).run();
      return null;
    }).when(executor).execute(any());
    
  • 89

    所谓问题的解决方案是使用 spy Mockito.spy(...)而不是 mock Mockito.mock(..) .

    Spy 使我们能够部分嘲笑 . Mockito擅长此事 . 因为你有一个不完整的类,所以你可以通过这种方式模拟这个类中需要的地方 .

相关问题