Reputation: 2375
I use spring retry and want to unit test it.
but could not get unit test working.
See My code & test below.
When I run the test, it says expected 3 times
but was 1 time
.
I must miss something. thanks
@RunWith(SpringJUnit4ClassRunner.class)
public class MyOperationsTest
private MyOperations myOperations;
@mock
Param1 param1;
@mock
Param2 param2AnotherOperation;
@Before
public void setUp(){
myOperations = new MyOperations(param1, param2AnotherOperation);
}
@Test
public void testmyMethodWithFailure_ShouldRetry3TimesThenThrowException() {
MyException exception1 = new MyException ("exception 1");
MyException exception2 = new MyException ("exception 2");
MyException exception3 = new MyException ("exception 3");
Mockito.doThrow(exception1).when(param2AnotherOperation).itsMethod(firstParam, secondParam);
Mockito.doThrow(exception2).when(param2AnotherOperation).itsMethod(firstParam, secondParam);
Mockito.doThrow(exception3).when(param2AnotherOperation).itsMethod(firstParam, secondParam);
Throwable writingException =
catchThrowable(() -> myOperations.myMethod(firstParam, secondParam));
Mockito.verify(param2AnotherOperation, times(3)).itsMethod(firstParam, secondParam);
}
in MyOperations class
@Service
@EnableRetry
public class MyOperations{
Param1 param1;
Param2AnotherOperation param2AnotherOperation
public MyOperations(Param1 param1, Param2AnotherOperation param2AnotherOperation) {
this.param1 = param1;
this.param2AnotherOperation = param2AnotherOperation;
}
@Retryable(value = {MyExceptoin.class},
maxAttemptsExpression = "3",
backoff = @Backoff(delayExpression = "#{@retryInterval}"))
public void myMethod(firstParam, secondParam){
try {
param2AnotherOperation.itsMethod(firstParam, secondParam);
...
}
catch(Exception ex){
throw new MyExceptoin(ex);
}
}
}
Upvotes: 1
Views: 6573
Reputation: 83
Like pointed out, for your retries to work, you need Spring to help you with that meaning you should be picking your bean from the Spring Context; so you will have to remove the explicit instantiation of the MyOperations
class. Also, your dependencies to the MyOperations class need to be inserted into the SpringContext (so they can be bound together in the context itself) and this can be done by annotation your mocked beans with @MockBean
. This will replace actual beans in the SpringContext with these mock beans. With all these in place, you will be able to leverage Spring's features like @Retryable
in your test.
So, something like:
@RunWith(SpringRunner.class)
public class MyOperationsTest
@MockBean // pushed 1st mocked dependency to Spring context
Param1 param1;
@MockBean // pushed 2nd mocked dependency to Spring context
Param2 param2AnotherOperation;
@Autowired //Getting the hydrated bean for class under test from context
private MyOperations myOperations;
@Before
public void setUp(){
// No manual instantiation required; picking bean from context
// myOperations = new MyOperations(param1, param2AnotherOperation);
...
}
... continue with tests ...
Upvotes: 1
Reputation: 174554
@EnableRetry
has to be on a @Configuration
class; you have it on a @Service
bean.
EDIT
Here's a quick hack to get you started; I haven't tested it but it should be close...
@RunWith(SpringRunner.class)
public class So52262230ApplicationTests {
private MyOperations myOperations;
@Autowired
Param1 param1;
@Autowired
Param2 param2AnotherOperation;
@Autowired
MyOperations myoperations;
@Test
public void testmyMethodWithFailure_ShouldRetry3TimesThenThrowException() {
MyException exception1 = new MyException("exception 1");
MyException exception2 = new MyException("exception 2");
MyException exception3 = new MyException("exception 3");
Mockito.doThrow(exception1).when(param2AnotherOperation).itsMethod(firstParam, secondParam);
Mockito.doThrow(exception2).when(param2AnotherOperation).itsMethod(firstParam, secondParam);
Mockito.doThrow(exception3).when(param2AnotherOperation).itsMethod(firstParam, secondParam);
Throwable writingException = catchThrowable(() -> myOperations.myMethod(firstParam, secondParam));
Mockito.verify(param2AnotherOperation, times(3)).itsMethod(firstParam, secondParam);
}
@Configuration
@EnableRetry
public static class Config {
@Bean
public Param1 param1() {
//return a mock
}
@Bean
public Param2 param2() {
//return a mock
}
@Bean
public MyOperations myOperations() {
return new MyOperations(param1(), param2());
}
}
}
Upvotes: 1