Java 如何使用在mockito中更改调用之间状态的相同参数验证相同mock方法的调用?
我有以下代码需要进行单元测试:Java 如何使用在mockito中更改调用之间状态的相同参数验证相同mock方法的调用?,java,unit-testing,mockito,Java,Unit Testing,Mockito,我有以下代码需要进行单元测试: public void foo() { Entity entity = //... persistence.save(entity); entity.setDate(new Date()); persistence.save(entity); } 我想验证一下,在第一次调用persistence.saveentity.getDate()时,返回null 因此,我无法使用Mockito.verify(/*…*/),因为当时方法foo
public void foo() {
Entity entity = //...
persistence.save(entity);
entity.setDate(new Date());
persistence.save(entity);
}
我想验证一下,在第一次调用persistence.save
entity.getDate()
时,返回null
因此,我无法使用Mockito.verify(/*…*/)
,因为当时方法foo
已经完成,并且调用了entity.setDate(Date)
因此,我认为我需要在调用发生时对调用进行验证。如何使用Mockito实现这一点?我创建了以下
Answer
实现:
public class CapturingAnswer<T, R> implements Answer<T> {
private final Function<InvocationOnMock, R> capturingFunction;
private final List<R> capturedValues = new ArrayList<R>();
public CapturingAnswer(final Function<InvocationOnMock, R> capturingFunction) {
super();
this.capturingFunction = capturingFunction;
}
@Override
public T answer(final InvocationOnMock invocation) throws Throwable {
capturedValues.add(capturingFunction.apply(invocation));
return null;
}
public List<R> getCapturedValues() {
return Collections.unmodifiableList(capturedValues);
}
}
用Mockitos
ArgumentCaptor
无法实现所呈现的Answer
实现所完成的捕获,因为这仅在调用测试中的方法之后使用。在我最初的评论中,这是我想到的答案
要模拟的类:
class MockedClass{
void save(SomeBean sb){
//doStuff
}
}
我们需要验证Date对象的类为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<Void>(){
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();
}
@测试
公共无效测试答案(){
MockedClass mc=Mockito.mock(MockedClass.class);
Mockito.doAnswer(新答案(){
布尔值checkDate=true;
@凌驾
公共Void应答(invocationmock调用)抛出可丢弃的{
SomeBean sb=(SomeBean)invocation.getArguments()[0];
if(checkDate&&sb.getDate()!=null){
抛出新的NullPointerException();//或更有意义的异常
}
checkDate=false;
返回null;
}}).when(mc).save(Mockito.any(SomeBean.class));;
TestClass tc=新的TestClass(mc);
tc.doWork();
}
第一次通过这个
答案(我应该在我的原始评论中使用这个术语),如果date不为null,这将抛出一个异常并使测试用例失败。第二次到,checkDate
将为false,因此将不执行检查。取消该项。。。没有注意到这是实现:-)澄清一下,听起来您想在第一次保存之后基本上检查日期是否为空?听起来,在第一次保存之后,您基本上是在注入一行代码。我不确定这是否可能。如果正在模拟的是persistence
,则如果save方法为null,则可以模拟该方法失败。@ChristopherSchneiderpersistence
是正在模拟的对象。但我不明白你的最后一句话。如果我不清楚,对不起。看看我的评论,我可以看出我没有很好地解释,但看起来你已经明白了。更具体地说,我的意思是,当您调用save()
时,这是一个模拟方法。如果第一次调用date时不为null,则会失败(例如,可以抛出RuntimeException)。第二次通过时,应设置为不失败。我将发布一个答案。当使用引发异常的自定义答案实现时,请确保被测试单元不会处理此类异常。
@Test
public void testAnswer(){
MockedClass mc = Mockito.mock(MockedClass.class);
Mockito.doAnswer(new Answer<Void>(){
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();
}