鉴于以下某些类的实现:
private Executor someSpecialExecutor;
private SomeService someService;
public void foo() {
someSpecialExecutor.execute(() -> someService.bar());
}
假设someSpecialExecutor
始终在当前线程中同步运行传递的runnable,如何验证someService.bar()
当前在someSpecialExecutor
中运行时是否调用Runnable
?< / p>
我知道我可以创建一个实现someService.bar()
的类,并检查执行程序是否传递了此类的实例,并在Runnable
的测试中检查Chess
的调用实现。但是我想避免为这个目的创建一个额外的类。
答案 0 :(得分:1)
好吧,你可以确保someService.bar()
在测试中只调用一次,这是verify
的默认值:
Mockito.verify(someService).bar();
如果被多次调用,则会失败。另一种更加确定的方法是模拟executoreService本身,然后使用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()应该被调用一次。
答案 1 :(得分:0)
由于您说someSpecialExecutor
将始终在当前线程中同步运行传递的Runnable
,因此您可以检查someService.bar()
中的当前调用堆栈以确定该方法是否在someSpecialExecutor
类的实例。
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()
内,这为您提供了更强的保证。