Home > front end >  Spring Retry always retry one time more than asked in test
Spring Retry always retry one time more than asked in test

Time:12-07

I'm new to Spring and trying to implement Spring Retry with a simple test. however i can't make it work, hope someone could show me where i've done wrong. Also I'm wondering, is it possible to write unit test to verify that Spring Retry has tried the requested maximum number of retries? because so far from google search, it seems it can only work in integration test because it needs Spring to set up the context first.

here is my main class:

@SpringBootApplication
public class SpringtestApplication {

  public static void main(String[] args) {
    new SpringApplicationBuilder(SpringtestApplication.class).run(args);
  }

}

the configuration class

@Configuration
@EnableRetry
public class FakeConfiguration implements ApplicationRunner {

  private final FakeParser fakeParser;

  public FakeConfiguration(FakeParser fakeParser) {
    this.fakeParser = fakeParser;
  }

  @Override
  public void run(ApplicationArguments args) {
    this.runParser();
  }

  @Retryable(maxAttempts = 5, value = RuntimeException.class)
  public void runParser() {
    fakeParser.add();
  }
}

the component/service class:

@Component
public class FakeParser {

  public int add(){
    int result = 113;
    return result;
  }
}

the retry test for it:

@RunWith(SpringRunner.class)
@SpringBootTest
class SpringtestApplicationTests {

  @Autowired
  private FakeConfiguration fakeConfiguration;

  @MockBean
  private FakeParser fakeParser;

  @Test
  public void retry5times(){
    when(fakeParser.add()).thenThrow(RuntimeException.class);

    try {
      fakeConfiguration.runParser();
    } catch (RuntimeException e){
    }

    verify(fakeParser, times(5)).add();
  }
}

however, the test didn't pass:

org.mockito.exceptions.verification.TooManyActualInvocations: 
fakeParser bean.add();
Wanted 5 times:
-> at com.example.springtest.SpringtestApplicationTests.retry5times(SpringtestApplicationTests.java:43)
But was 6 times:
-> at com.example.springtest.FakeConfiguration.runParser(FakeConfiguration.java:26)
-> at com.example.springtest.FakeConfiguration.runParser(FakeConfiguration.java:26)
-> at com.example.springtest.FakeConfiguration.runParser(FakeConfiguration.java:26)
-> at com.example.springtest.FakeConfiguration.runParser(FakeConfiguration.java:26)
-> at com.example.springtest.FakeConfiguration.runParser(FakeConfiguration.java:26)
-> at com.example.springtest.FakeConfiguration.runParser(FakeConfiguration.java:26)

CodePudding user response:

when(someObject.someMethod()) evaluates the method and makes a real call to it. That's why you're always getting one more invocation than wanted.

If you need to count the actual invocations you could either add 1 to your verify, but that is an ugly workaround that is not recommended (and also not needed). Or you can use the Mockito.doXXX methods that don't have that problem.

In your case you could try

doThrow(new RuntimeException()).when(fakeParser).add();

This should give you the correct amount of invocations in the end. Notice the difference in the usages of when here: when(fakeParser).add() (two methods chained together) vs when(fakeParser.add()) (only one method)

CodePudding user response:

Most probably you try with

Mockito.verify(fakeParser,times(5)).add(Mockito.any());

You should think about first run because when you retry 5 times and run once again. It should be 6 run even if you retry 5 times.

You are forgetting first exceptional case which is normal run behaviour

  • Related