英文:
Mockito verify lambda is called n-times
问题
I see that you want to test whether the repo.getData()
method is called a specific number of times when an error occurs in your Service
class. It seems like you're using Mockito for mocking and testing. The issue you're facing is that getData()
is never called during the test.
Here's a corrected version of your test code:
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
@InjectMocks
Service service;
@Mock
Repository repository;
@Mock
RetryHelper<Collection<String>> retryHelper;
@Captor
ArgumentCaptor<RetryHelper.Operation<Collection<String>>> operation;
@Before
public void setUp() throws Exception {
when(retryHelper.doWithRetry(any())).thenAnswer(invocation -> {
RetryHelper.Operation<Collection<String>> op = invocation.getArgument(0);
return op.doIt();
});
}
@Test
public void shouldRetryIfDataQueryFailsForNonFatalError() throws Exception {
when(repository.getData())
.thenThrow(new RuntimeException("Runtime Exception"));
service.callService();
verify(retryHelper).doWithRetry(operation.capture());
// Assert that the operation was retried 2 times
verify(repository, times(2)).getData();
}
}
Here are the changes I made to your code:
-
Added
@RunWith(MockitoJUnitRunner.class)
to your test class to enable Mockito annotations automatically. -
Used
@InjectMocks
for theService
class,@Mock
for the other dependencies, and@Captor
for capturing theRetryHelper.Operation
argument. -
In the
setUp
method, I mocked the behavior ofretryHelper.doWithRetry
to capture the operation passed to it and execute it immediately. This is necessary to trigger the retry logic.
With these changes, the test should now verify that the getData()
method is called twice when an exception is thrown.
英文:
I need to test if a lambda function is called n-times from a service instance.
I have a Service class, that interact with the repository, when an error occur on retriving data from repository the service should retry until a max number of retries is reached so I have implemented as follow:
interface Repository {
Collection<String> getData();
}
public class RetryHelper<T> {
private Integer retries;
public RetryHelper(Integer retries) {
this.retries = retries;
}
public interface Operation<T> {
T doIt() throws Exception;
}
public T doWithRetry(Operation<T> operation) throws Exception {
int remainRetries = retries;
do {
try {
return operation.doIt();
} catch (Exception e) {
if (remainRetries == 0) {
throw e;
}
//TODO: wait before retry
remainRetries--;
}
} while (true);
}
}
class Service {
@Inject
Repository repo;
private final RetryHelper<Collection<String>> retryHelper;
public Collection<String> callService() {
try {
Collection<String> res = retryHelper.doWithRetry(() ->
repo.getData());
return res;
} catch (Exception e) {
throw (CustomException) e;
}
}
}
I need to test using Mockito that repo.getData()
is called n-times when error occurs. I can change the Service
code and the RetryHelper
, so I am open to suggestions.
I have try to implment the test following tutorials and documentations:
public class ServiceTest {
@Inject
Service service;
@InjectMock
Repository repository;
@InjectMock
RetryHelper<Collection<String>> retryHelper;
@Captor
ArgumentCaptor<RetryHelper.Operation<Collection<String>>> operation;
@BeforeEach
void init_mocks() {
MockitoAnnotations.openMocks(this);
}
@Test
void shouldRetryIfDataQueryFailsForNonFatalError() throws Exception {
when(repository.getData())
.thenThrow(new RuntimeException("Runtime Exception"));
service.callService();
verify(retryHelper).doWithRetry(operation.capture());
verify(repository, times(2)).getData();
}
}
The test fail with message that getData()
is never called.
答案1
得分: -1
我终于找到了不使用`Captor`的解决方案
public class ServiceTest {
@Inject
Service service;
@InjectMock
Repository repository;
@Inject
RetryHelper<Collection<String>> retryHelper;
@Test
void shouldRetryIfDataQueryFailsForNonFatalError() throws Exception {
when(repository.getData())
.thenThrow(new RuntimeException("Runtime Exception"));
try {
service.callService();
} catch(Exception e) {
verify(repository, times(2)).getData();
}
}
}
英文:
I have finally found the solution without using Captor
public class ServiceTest {
@Inject
Service service;
@InjectMock
Repository repository;
@Inject
RetryHelper<Collection<String>> retryHelper;
@Test
void shouldRetryIfDataQueryFailsForNonFatalError() throws Exception {
when(repository.getData())
.thenThrow(new RuntimeException("Runtime Exception"));
try {
service.callService();
} catch(Exception e) {
verify(repository, times(2)).getData();
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论