如何使用在mockito中调用之间更改状态的相同参数来validation相同模拟方法的调用?
我有以下代码进行unit testing:
public void foo() { Entity entity = //... persistence.save(entity); entity.setDate(new Date()); persistence.save(entity); }
我想validation在第一次调用persistence.save
entity.getDate()
返回null
。
因此,我无法使用Mockito.verify(/*...*/)
因为那时方法foo
已经完成,并且entity.setDate(Date)
。
所以我认为我需要在调用发生时对调用进行validation。 我如何使用Mockito做到这一点?
我创建了以下Answer
实现:
public class CapturingAnswer implements Answer { private final Function capturingFunction; private final List capturedValues = new ArrayList (); public CapturingAnswer(final Function capturingFunction) { super(); this.capturingFunction = capturingFunction; } @Override public T answer(final InvocationOnMock invocation) throws Throwable { capturedValues.add(capturingFunction.apply(invocation)); return null; } public List getCapturedValues() { return Collections.unmodifiableList(capturedValues); } }
此答案捕获正在进行的调用的属性。 capturedValues
值可以用于简单的断言。 该实现使用Java 8 API。 如果这不可用,则需要使用能够将InvocationOnMock
转换为捕获值的接口。 测试用例中的用法如下:
@Test public void testSomething() { CapturingAnswer captureDates = new CapturingAnswer<>(this::getEntityDate) Mockito.doAnswer(captureDates).when(persistence).save(Mockito.any(Entity.class)); service.foo(); Assert.assertNull(captureDates.getCapturedValues().get(0)); } private Date getEntityDate(InvocationOnMock invocation) { Entity entity = (Entity)invocation.getArguments()[0]; return entity.getDate(); }
使用Mockitos ArgumentCaptor
无法实现由呈现的Answer
实现完成的捕获,因为这仅在调用被测方法之后使用。
在我原来的评论中,这是我想到的答案。
要嘲笑的课程:
class MockedClass{ void save(SomeBean sb){ //doStuff } }
我们需要validationDate对象的类是null。
class SomeBean{ Date date; Date getDate(){return date;} void setDate(Date date){this.date=date;} }
被测试的课程:
class TestClass{ MockedClass mc; TestClass(MockedClass mc){this.mc = mc;} void doWork(){ SomeBean sb = new SomeBean(); mc.save(sb); sb.setDate(new Date()); mc.save(sb); } }
和测试用例:
@Test public void testAnswer(){ MockedClass mc = Mockito.mock(MockedClass.class); Mockito.doAnswer(new Answer(){ boolean checkDate = true; @Override public Void answer(InvocationOnMock invocation) throws Throwable { SomeBean sb = (SomeBean) invocation.getArguments()[0]; if(checkDate && sb.getDate() != null){ throw new NullPointerException(); //Or a more meaningful exception } checkDate = false; return null; }}).when(mc).save(Mockito.any(SomeBean.class));; TestClass tc = new TestClass(mc); tc.doWork(); }
第一次通过这个Answer
(我应该在我的原始评论中使用的术语),如果date不为null,这将抛出exception并使测试用例失败。 第二次, checkDate
将为false,因此不会执行检查。