给定某些类的以下实现:
private Executor someSpecialExecutor;
private SomeService someService;
public void foo() {
someSpecialExecutor.execute(() -> someService.bar());
}
假设someSpecialExecutor
始终在当前线程中同步运行传递的运行,我该如何验证someService.bar()
当前在someSpecialExecutor
中运行而不是在其外部运行时?
我知道我可以创建一个实现Runnable
的类,并检查执行程序是否通过此类的实例,并在Runnable
实现的测试中检查someService.bar()
的调用。但是我想避免为此目的创建其他类。
好吧,您可以确保someService.bar()
仅在测试中被调用一次,这是verify
的默认值:
Mockito.verify(someService).bar();
如果被称为多次,这将失败。更确定的另一种方法是嘲笑执行权限本身,然后使用ArgumentCaptor
。
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
Mockito.verify(someSpecialExecutor).execute( captor.capture() );
Mockito.verify(someService, Mockito.never()).bar(); // nothing has been executed yet
Runnable runnable = captor.getValue(); // get the actual argument
runnable.run(); // execute the runnable
Mockito.verify(someService).bar(); // now the lambda should have executed the method
以这种方式,您可以模拟执行者,然后检查执行方法是否被调用一次(不实际执行某些内容)。此时,不应调用someService.bar()方法。不,您会收到传递给执行人并执行它的参数 - 现在应该调用一次someService.bar()。
,因为您说 someSpecialExecutor
将始终在当前线程中同步运行传递的 Runnable
,因此您可以检查someService.bar()
内的当前调用堆栈以确定该方法是否在someSpecialExecutor
实例中运行S类。
class SomeService {
public void bar() {
// check whether we've been called by 'someSpecialExecutor'
boolean inside = false;
StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
for (StackTraceElement frame : callStack) {
if (frame.getMethodName().equals("execute") &&
frame.getClassName().equals(someSpecialExecutor.getClass().getName())) {
inside = true;
break;
}
}
System.out.println("bar: " + inside);
}
}
但是,这并不一定保证您在someSpecialExecutor
中,可能是代码是由同一类的某些不同实例执行的。
但是,通过扩展上述方法,您可以进一步测试呼叫堆栈,看看您是否在foo()
中,这为您提供了更强的保证。