如何使用 mockito 在匿名类中测试方法调用

2022-09-03 02:05:54
@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)的调用。

任何人都可以建议我如何测试这种情况吗?

以下是我尝试测试的示例:

 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:


答案 1

以下是上述方案的解决方案。由于我对测试newTransactionTemplate.execute()的调用不感兴趣,它是一个弹簧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)); 

答案 2

从何而来?如果你通过 的构造函数或 setter 注入它,你可以通过一个 mock。reserveServiceSomeClass

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

推荐