2017-11-21 2 views
1

일부 클래스의 다음 구현을 감안할 때 : 현재 그것의 외부 someSpecialExecutor에서 실행하지 않을 때는 항상 현재 스레드에서 동 기적으로 전달 된 실행 가능한을 실행일부가 실행 프로그램의 본문으로 호출되었는지 확인하는 방법은 무엇입니까?

private Executor someSpecialExecutor; 

private SomeService someService; 

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

someSpecialExecutor한다고 가정을, 어떻게 someService.bar()가 호출되어 있는지 확인 않습니다 ?

Runnable을 구현하는 클래스를 만들고 실행자가이 클래스의 인스턴스를 전달하고 Runnable 구현의 테스트에서 someService.bar()의 호출을 확인하는지 확인할 수 있습니다. 그러나 나는이 단일 목적을 위해 추가 수업을 만드는 것을 피하고 싶습니다.

+0

"외부에서가 아니라 someSpecialExecutor에서 현재 실행 중일 때 호출됩니까?" - 테스트에서'bar()'를 (명시 적으로) 호출하지 않았습니다. 따라서 *'bar()'가 전혀 실행되면'execute()'에서 시작해야합니다. – JimmyB

+0

@JimmyB 구현이 다음과 같이 변경되면 테스트를 실패합니다.'someSpecialExecutor.execute (() -> {}); someService.bar();' – SpaceTrucker

+0

'bar'가 다른 * executor의 내부에서 호출되는지 여부가 중요합니까? 다른 말로하면, 그것은 특별히'someSpecialExecutor'일까요, 아니면 "직접 호출"과 "서비스를 통한 호출"에 관심이 있습니까? – Thomas

답변

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 

이렇게하면 실행 프로그램을 조롱 한 다음 execute 메소드가 실제로는 (실제로는 실행하지 않고) 호출되는지 확인합니다. 이 시점에서 someService.bar() 메서드가 호출되어서는 안됩니다. Executor에 전달 된 인수를 가져 와서 실행하지 마십시오. 이제 someService.bar()가 한 번 호출되어야합니다. 당신이 someSpecialExecutor은 항상 현재 스레드에서 동 기적으로 전달 Runnable를 실행 말 때문에

+0

첫 번째 것은 다음과 같이 실패하지 않을 것이다 :'someSpecialExecutor.execute (() -> {}); someService.bar();'. 하지만 두 번째 옵션은 좋아 보인다. – SpaceTrucker

0

, 당신은 방법 someSpecialExecutor의 클래스의 인스턴스에서 실행되고 있는지 확인하기 위해 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); 
    } 
} 

그러나이 반드시 당신이 someSpecialExecutor 내부에있어 보증하지 않습니다, 그것은 코드가 같은 클래스의 일부 다른 인스턴스에 의해 실행되어있을 수 있습니다.

그러나 위의 방법을 확장하면 호출 스택을 추가로 테스트하여 사용자가 더 강한 보증을 제공하는 foo() 안에 있는지 확인할 수 있습니다.

+0

스택 추적을 사용하는 대신 내부 변수를 설정하는 위조 실행 프로그램과이를 검사하는 서비스 모의를 사용할 수 있습니다. –

+0

그건 코딩의 아름다움입니다. 당신이 할 수있는 많은 방법이 있습니다. – Thomas

관련 문제