2011-05-05 3 views
3
@Transactional(propagation = Propagation.REQUIRED) 
    public void exe() { 
     try { 
      Reserve reserveInfo = newTransactionTemplate.execute(new TransactionCallback<Reserve>() { 
       @Override 
       public Reserve doInTransaction(TransactionStatus status) { 
        return reserveService.callReserve(reserveDetails); 
       } 
      }); 
      if(reserveInfo != null && reserveInfo.getStatus()=="DONE") { 
      someOtherService.doSomething(); 
      } 
     } finally { 
      if(reserveInfo!= null && reserveInfo.getStatus().equals("DONE")){ 
       final String id = reserveInfo.getId();         
       Release releaseInfo = newTransactionTemplate.execute(new TransactionCallback<Release>() { 
        @Override 
        public Release doInTransaction(TransactionStatus status) { 
         return reserveService.callRelease(id); 
        } 
       });    
       if (releaseInfo.getStatus() != "RELEASED") { 
        throw new RuntimeException("Problem in releaseing"); 

       } 
      } 
     }  
    } 

테스트 할 샘플 코드입니다. 나는 그물에 익명의 클래스를 테스트 할 때 많은 것을 발견 할 수 없었다. exe ​​() 메서드를 테스트하고 newTransactionTemplate.execute 메서드를 통해 호출하여 reserveService.callReserve (reserveDetails)에 대한 호출을 모의 처리하려고합니다.mockito를 사용하여 익명 클래스 내에서 메서드 호출을 테스트하는 방법

어떤 상황에서도이 상황을 어떻게 테스트 할 수 있습니까?

private SomeService someService = null; 
    @Mock 
    private ReserveService mockReserveService; 
    @Mock 
    private ReleaseService mockReleaseService; 
    @Mock 
    private TransactionTemplate mockTransactionTemplate; 
    @Mock 
    private SomeOtherService mockSomeOtherService;  
    @BeforeMethod 
    public void setup() throws Exception { 
     MockitoAnnotations.initMocks(this); 
     someService = new SomeService(); 
     someService.setReserveService(mockReserveService); 
     someService.setReleaseService(mockReleaseService); 
     someService.setSomeOtherService(mockSomeOtherService); 
     someService.setNewTransactionTemplate(mockTransactionTemplate); 
    } 
    @Test(enabled=true) 
    public void exeHappyPath() { 
     Reserve reserveInfo = new Reserve(); 
     reserveInfo.setId("123"); 
     reserveInfo.setStatus("DONE"); 
     Release releaseInfo = new Release(); 
     releaseInfo.setStatus("RELEASED"); 
     when(mockReserveService.callReserve(Mockito.any(ReserveDetails.class))).thenReturn(reserveInfo); 
     when(mockReserveService.callRelease(reserveInfo.getId())).thenReturn(releaseInfo); 
     when(mockTransactionTemplate.execute(Mockito.<TransactionCallback<Reserve>>any())).thenReturn(reserveInfo); 
     when(mockTransactionTemplate.execute(Mockito.<TransactionCallback<ReleaseInfo>>any())).thenReturn(releaseInfo); 
     //Call the exe method 
     someService.exe(); 

     verify(mockReserveService, times(1)).callReserve(Mockito.any(ReserveDetails.class)); 
     verify(mockReserveService, times(1)).callRelease(reserveInfo.getId())); 
     verify(mockSomeOtherService, times(1)).doSomthing()); 

    } 

java.lang.ClassCastException가 (mockTransactionTemplate.execute이 .. releaseInfo 반환 개체 발생과 때와 두 번째 호출 :

답변

5

여기에 위에서 언급 한 시나리오의 해결책이 있습니다. newTransactionTemplate.execute()의 호출을 테스트하는 데 관심이 없었기 때문에 이것이 스프링 API입니다. reserveService.callReserve (reserveDetails)reserveService.callRelease (id)의 호출을 테스트하고 싶습니다. 이것을 테스트하는 유일한 방법은 바로 통과하는 transactiontemplate/transactioncallback "실제"구현/스텁을 만드는 경우입니다. 따라서 doIntransaction 메소드는 액션을 수행하는 것 이상을 수행해야합니다. 이 경우 액션 메소드에 대한 기대치를 설정할 수 있습니다.이 경우에는 reserveService입니다.

when(mockTransactionTemplate.execute(Mockito.<TransactionCallback>any())).thenAnswer(new Answer() { 
     public Object answer(InvocationOnMock invocation) { 
      Object[] args = invocation.getArguments(); 
      TransactionCallback arg = (TransactionCallback)args[0]; 
      return arg.doInTransaction(new SimpleTransactionStatus()); 
     } 
    });  
    when(mockResourceService.callReserve(any(ReserveDetails.class))).thenReturn(reserveInfo); 
    when(mockResourceService.callRelease(eq(id))).thenReturn(releaseInfo); 

    //Call the exe method 
    someService.exe(); 

    verify(mockResourceService, times(1)).callReserve(any(ReserveDetails.class)); 
    verify(mockSomeOtherService, times(1)).doSomthing()); 
    verify(mockMemberResourceService, times(1)).callRelease(eq(id)); 
1

여기

내가 테스트를 시도하고 어떻게 샘플입니다 어디 reserveService은 오는가? 당신이 SomeClass의 생성자 또는 세터 중 하나를 통해 주입하는 경우, 대신 모의를 전달할 수 있습니다.

// Set up your mock and stub out the method call 
ReserveService reserveService = mock(ReserveService.class); 
when(reserveService.callReserve(any(ReserveDetails.class))).thenReturn(null); 

// Inject, either via constructor or setter 
SomeClass instance = new SomeClass(reserveService); 
// Or, instance.setReserveService(reserveService); 
+0

예 .ReserveService는 속성을 통해 주입됩니다. – Anj

+0

예 .ReserveService는 속성을 통해 주입됩니다. 이 테스트는 속성을 통해 주입되는 newTransactionTemplate.execte() 메서드에 대한 호출을 포함합니다. – Anj

+0

'ReserveService reserveService = mock (ReserveService.class); TransactionTemplate newTransactionTemplate = mock (TransactionTemplate.class); SomeClass 인스턴스 = new SomeClass(); instance.setReserveService (reserveService); instance.setNewTransactionTemplate (newTransactionTemplate); 이제 'SomeClass # exe()'를 호출 할 수 있지만 이것이 당신을 위해 무엇을 할 것인지 정확히는 알 수 없습니다. 정확하게 테스트하려고하는 것은 무엇입니까? –

관련 문제