如何验证某些东西被调用为某个执行者的身体?

时间:2017-11-21 09:30:05

标签: java unit-testing mockito

鉴于以下某些类的实现:

private Executor someSpecialExecutor;

private SomeService someService;

public void foo() {
    someSpecialExecutor.execute(() -> someService.bar());
}

假设someSpecialExecutor始终在当前线程中同步运行传递的runnable,如何验证someService.bar()当前在someSpecialExecutor中运行时是否调用Runnable?< / p>

我知道我可以创建一个实现someService.bar()的类,并检查执行程序是否传递了此类的实例,并在Runnable的测试中检查Chess的调用实现。但是我想避免为这个目的创建一个额外的类。

2 个答案:

答案 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()内,这为您提供了更强的保证。