mockito:有没有办法捕获存根方法的返回值?

Itt*_*ayD 17 java mockito

如果我模拟一个方法来返回某个对象的新实例,我该如何捕获返回的实例?

例如:

 when(mock.someMethod(anyString())).thenAnswer(new Answer() {
     Object answer(InvocationOnMock invocation) {
         Object[] args = invocation.getArguments();
         Object mock = invocation.getMock();
         return new Foo(args[0])
     }
 });
Run Code Online (Sandbox Code Playgroud)

显然,我可以有一个Foo类型的字段,answer并将其设置为新实例,但是有更好的方法吗?像ArgumentCaptor这样的东西?

Jef*_*ley 23

我想做类似的事情,但是使用间谍对象而不是模拟.具体来说,给定一个间谍对象,我想捕获返回值.根据Andreas_D的回答,这就是我想出的.

public class ResultCaptor<T> implements Answer {
    private T result = null;
    public T getResult() {
        return result;
    }

    @Override
    public T answer(InvocationOnMock invocationOnMock) throws Throwable {
        result = (T) invocationOnMock.callRealMethod();
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

预期用途:

// spy our dao
final Dao spiedDao = spy(dao);
// instantiate a service that does some stuff, including a database find
final Service service = new Service(spiedDao);

// let's capture the return values from spiedDao.find()
final ResultCaptor<QueryResult> resultCaptor = new ResultCaptor<>();
doAnswer(resultCaptor).when(spiedDao).find(any(User.class), any(Query.class));

// execute once
service.run();
assertThat(resultCaptor.getResult()).isEqualTo(/* something */);

/// change conditions ///

// execute again
service.run();
assertThat(resultCaptor.getResult()).isEqualTo(/* something different */);
Run Code Online (Sandbox Code Playgroud)


And*_*s_D 9

看起来你要观察Answer实例和接收notfications每个时间answer方法被调用(这将触发新的创造Foo).那么为什么不发明一个ObservableAnswer类:

public abstract class ObservableAnswer implements Answer {
  private Listener[] listeners; // to keep it very simple...

  public ObservableAnswer(Listener...listeners) {
    this.listeners = listeners;
  }

  @Override
  public Object answer(InvocationOnMock invocation) {
    Object answer = observedAnswer(invocation);
    for (Listener listener:listeners) {
       listener.send(answer);
    }
    return answer;
  }

  // we'll have to implement this method now
  public abstract Object observedAnswer(InvocationOnMock invocation);
}
Run Code Online (Sandbox Code Playgroud)

有可能的使用:

Listener[] myListenerns = getListeners();  // some magic (as usual)
when(mock.someMethod(anyString())).thenAnswer(new ObservableAnswer(myListeners) {
     Object observedAnswer(InvocationOnMock invocation) {
         Object[] args = invocation.getArguments();
         Object mock = invocation.getMock();
         return new Foo(args[0])
     }

 });
Run Code Online (Sandbox Code Playgroud)