如何监视使用 Callable<T> arg 实例化并使用 Mockito 实现 Closeable 的对象?

How to spy on an object that is instantiated with Callable<T> arg and implements Closeable with Mockito?

我正在尝试找出如何通过使用 Mockito 并监视对象来跳过单元测试中的非静态 void 方法调用。

有问题的 class 是:

public class CallableExecutor<T> implements Closeable {

  public CallableExecutor( String s, Callable<T> c ) {
     this.s = s;
     this.c = c;
  }

  public void methodWeAreTryingToSkip( String string ) {
     // some logic
  }

}

我尝试进行单元测试的方法是:

public String myMethodThatIsBeingUnitTested( args ) {
   AtomicReference<String> id = new AtomicReference<>();
   try ( CallableExecutor<String> executor = new CallableExecutor<>(
      someString, () -> { id.set( someMethodCall ) );
      return id.get();
    } ) ) {
      executor.methodWeAreTryingToSkip( string );
    }
    catch ( Exception e ) {
      // exception handling
    }
}

在我的单元测试中,我尝试了下面概述的代码,但最终都在“doNothing()”行之前抛出了 Mockito 错误(底部的详细错误):

CallableExecutor<String> mockExecutor = spy( new CallableExecutor<>( any(), any() ) );
doNothing().when( mockExecutor ).methodWeAreTryingToSkip( anyString() );
Callable callable = mock( Callable.class );
CallableExecutor<String> mockExecutor = spy( new CallableExecutor<>( anyString(), eq( callable ) ) );
doNothing().when( mockExecutor ).methodWeAreTryingToSkip( anyString() );

错误:

Misplaced or misused argument matcher detected here
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(any());
    verify(mock).someMethod(contains("foo"))

This message may appear after an NullPointerException if the last matcher is returning an object 
like any() but the stubbed method signature expect a primitive argument, in this case,
use primitive alternatives.
    when(mock.get(any())); // bad use, will raise NPE
    when(mock.get(anyInt())); // correct usage use

Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(any());
    verify(mock).someMethod(contains("foo"))

This message may appear after an NullPointerException if the last matcher is returning an object 
like any() but the stubbed method signature expect a primitive argument, in this case,
use primitive alternatives.
    when(mock.get(any())); // bad use, will raise NPE
    when(mock.get(anyInt())); // correct usage use

Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.

如有任何帮助或建议,我们将不胜感激!

你写了

spy( new CallableExecutor<>( any(), any() ) );

你不能这样做。您需要先创建一个实际的 CallableExecutor 对象,然后才能监视它。这意味着将实际值传递给它的构造函数,而不是传递匹配器方法的输出。

匹配器方法通过操纵 Mockito 用来存储存根和验证信息的内部结构来工作。这就是为什么您只能在存根或验证期间使用它们。

将实际的 non-matcher 个参数传递给 CallableExecutor 构造函数。