簡體   English   中英

如何使用 mockito 在匿名 class 中測試方法調用

[英]How to test a method invocation inside an anonymous class using mockito

@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");

                }
            }
        }       
    }

這是我要測試的示例代碼。 我在網上測試匿名 class 時找不到太多東西。 我想通過 newTransactionTemplate.execute 方法測試 exe() 方法 go 並模擬對 reserveService.callReserve(reserveDetails) 的調用。

任何機構都可以建議我如何測試這種情況嗎?

這是我嘗試測試的示例:

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

    }

第二次調用 when(mockTransactionTemplate.execute.. with return object releaseInfo 拋出 java.lang.ClassCastException:

這是上述場景的解決方案。 因為我對測試newTransactionTemplate.execute()的調用不感興趣,所以它是 spring API。 我想測試reserveService.callReserve(reserveDetails)reserveService.callRelease(id)的調用。 測試這一點的唯一方法是,如果我們創建一個只是通過的事務模板/事務回調“真實”實現/存根。 所以 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)); 

reserveService是從哪里來的? 如果您通過SomeClass的構造函數或 setter 注入它,則可以改為傳遞模擬。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM