如何使模拟无效方法与mockito

如何用void返回types来模拟方法?

我实现了观察者模式,但是我不能用Mockito来嘲笑它,因为我不知道如何。

我试图在互联网上find一个例子,但没有成功。

我的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(); } 

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

看看Mockito API文档 。 正如链接文件提到的(点#12),您可以使用doThrow()任何doThrow()doAnswer()doNothing()doReturn()系列方法来模拟void方法。

例如,

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

或者如果您想要将其与后续行为相结合,

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

假设你正在嘲笑Setter setState(String s)类中的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()); 

我想我已经find了一个简单的答案来解决这个问题,只需要一个方法来调用真正的方法(即使它有一个void return),你可以这样做:

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

或者,你可以为这个类的所有方法调用真正的方法,这样做:

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

所谓问题的解决scheme是使用spy Mockito.spy(…)而不是mock Mockito.mock(..) 。

间谍让我们部分嘲笑。 Mockito擅长这件事。 因为你有不完整的课,所以你在这个课上嘲笑了一些必要的地方。

加上@sateesh说的,当你只是想嘲笑一个无效的方法,以防止testing调用它,你可以这样使用一个Spy

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

当你想运行你的testing时,确保你调用了spy对象的testing方法,而不是world对象。 例如:

 assertEquals(0,spy.methodToTestThatShouldReturnZero()); 

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

 import static org.mockito.Mockito.*; 

对于部分嘲讽,仍然保持其他原始functionmockito提供“间谍”。

你可以使用它如下:

 private World world = spy(World.class); 

要消除执行的方法,你可以使用这样的东西:

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

给一个方法使用“then”时使用“thenReturn”一些自定义行为:

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

有关更多示例,请在文档中findmockito示例。

如何用mockito来模拟void方法 – 有两种select:

  1. doAnswer – 如果我们想要我们的虚拟无效方法做一些事情(嘲笑行为,尽pipe是无效的)。
  2. doThrow – 如果你想从Mockito.doThrow()的void方法抛出一个exception,那么就有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"); } } 

你可以find更多的细节,如何在我的文章中用Mockito来模拟testing void方法如何用Mockito模拟(一个带有例子的综合指南)

增加另一个答案的一堆(没有双关语意图)…

如果你不能\不想使用间谍,你需要调用doAnswer方法。 但是,您不一定需要推出自己的答案 。 有几个默认的实现。 值得注意的是, CallsRealMethods 。

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

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

要么:

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

我认为你的问题是由于你的testing结构。 我发现很难将混淆与在testing类中实现接口的传统方法混淆(正如您在这里所做的那样)。

如果您将侦听器实现为模拟,则可以validation交互。

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

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

@ashley:为我工作

 public class AssetChangeListenerImpl extends AbstractAssetChangeListener implements AssetChangeListener { @Override public void onChangeEvent(final EventMessage message) throws EventHubClientException { execute(message); } } } public class AbstractAssetChangeListener { protected void execute( final EventMessage message ) throws EventHubClientException { executor.execute( new PublishTask(getClient(), message) ); } } @RunWith(MockitoJUnitRunner.class) public class AssetChangeListenerTest extends AbstractAssetChangeListenerTest { public void testExecute() throws EventHubClientException { EventMessage message = createEventMesage(EventType.CREATE); assetChangeListener.execute(message); verify(assetChangeListener, times(1)).execute(message); } }