代码之家  ›  专栏  ›  技术社区  ›  SpaceTrucker

如何验证某个执行者的主体是否调用了某个对象?

  •  1
  • SpaceTrucker  · 技术社区  · 7 年前

    给定某个类的以下实现:

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

    假设 someSpecialExecutor 始终在当前线程中同步运行传递的runnable,如何验证 someService.bar() 当前运行时调用 一些特殊的执行器 而不是在它之外?

    我知道我可以创建一个实现 Runnable 并检查是否向执行器传递了该类的实例,并检查 一些服务。条形图() 在测试中 可运行 实施但我希望避免为这个单一目的创建额外的类。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Florian Schaetz    7 年前

    好吧,你可以确定 someService.bar() 在测试中只调用了一次,这是 verify :

    Mockito.verify(someService).bar();
    

    如果多次调用,则会失败。另一种更可靠的方法是模拟ExecuteService本身,然后使用 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
    

    这样,您可以模拟执行器,然后检查execute方法是否被调用一次(实际上没有执行某些操作)。此时,someService。不应调用bar()方法。不,你得到传递给执行者的参数并执行它——现在是someService。bar()应该被调用一次。

        2
  •  0
  •   Thomas    7 年前

    既然你这么说 someSpecialExecutor 将始终运行已通过的 Runnable 在当前线程中,可以同步地检查内部的当前调用堆栈 someService.bar() 确定该方法是否正在的实例中运行 一些特殊的执行器 的类。

    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);
        }
    }
    

    然而,这并不一定保证你在里面 一些特殊的执行器 ,可能是代码由同一类的某个不同实例执行。

    然而,通过扩展上述方法,您可以额外测试调用堆栈,看看您是否在其中 foo() 这给了你更有力的保证。