@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");
}
}
}
}
This is the sample code I want to test. I couldn't find much on testing anonymous class on net. I want to test the exe() method, go through newTransactionTemplate.execute method and mock the call to reserveService.callReserve(reserveDetails).
Can any body please suggest how can I test this situation?
here is the sample how i'm trying to test:
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");
wh开发者_如何学运维en(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());
}
The second call to when(mockTransactionTemplate.execute.. with return object releaseInfo throws java.lang.ClassCastException:
Here is the solution to the above mentioned scenario. As I was not interested in testing the invocation of newTransactionTemplate.execute(), it being an spring API. I wanted to test the invocation of reserveService.callReserve(reserveDetails) and reserveService.callRelease(id). The only way to test this is if we create a transactiontemplate/transactioncallback "real" implementation/stub that is just pass thru. so the doIntransaction method should do nothing more than execute the action. then we can set expectation on the action methods which in this case is the 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));
Where does reserveService
come from? If you are injecting it through either SomeClass
's constructor or a setter, you can pass a mock instead.
// 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);
精彩评论