0

I am trying to test, if my method call was retried several times if some exception takes place. And if I call method directly, it works okay. But if I call it in separate thread, my test method fails it doesn't see any retry attemps. That's my methods:

public class MyClass {
        @Inject
        private ServiceClass service;

        @Retryable(value = {Exception.class}, maxAttempts = 5, backoff = @Backoff(delay = 30000))
        public void retryMethod(Integer id, double dId)
        {
            Thread remoteDIUpdater = new Thread(() -> {
            service.updateIndex(id, dId);
            }
            );
        remoteDIUpdater.setDaemon(true);
        remoteDIUpdater.setName("RemoteDIUpdaterThread");
        remoteDIUpdater.start();
        }

        @Recover
        public void recover(Exception ex, Integer id, double dId)
        {
            logger.error("Error", ex);
        }
}

And this is my test class:

public class TestClass
{
    @Inject
    @InjectMocks
    private MyClass myClass;

    @Mock     
    private private ServiceClass service;

    @Test
    public void testMethod()
    {
        Integer id = 1;
        double dId = 2d;
        doThrow(Exception.class).when(service).retryMethod(id, dId);
        myClass.updateBetDangerIndex(betId, dangerIndex);
        verify(service, Mockito.times(5)).retryMethod(null, id, iId);
    }

}

Maybe my test method is wrong. BUT if I call my method simply like this (withot thread):

@Retryable(value = {Exception.class}, maxAttempts = 5, backoff = @Backoff(delay = 30000))
            public void retryMethod(Integer id, double dId)
            {             
                service.updateIndex(id, dId);              
            }

, my test method runs ok. What is the mistake?

Sviatlana
  • 1,728
  • 6
  • 27
  • 55
  • 1
    Your test is wrong. You are mocking things and creating a new instance yourself (basically the `@Inject` is useless) and as such `@Retry` will do nothing. – M. Deinum Oct 16 '17 at 09:07
  • I am using test spring context and inject works well. My test works good withput multithreading. – Sviatlana Oct 16 '17 at 09:10
  • No it doesn't... The `@InjectMocks` renders the `@Inject` useless as it will construct a new instance and inject the mocked dependencies into it. It will not use the instance injected by Spring. Hence your test is just wrong. – M. Deinum Oct 16 '17 at 09:53
  • I simplyfied my code and maybe made a mistake or not mentioned smth. The problem is not in @|nject or smth like this. Don't know how to test such multithreaded app. – Sviatlana Oct 16 '17 at 09:55
  • Yes it is the problem... the `@Retry` works with AOP, which is applied through Spring. As you are using `@ InjectMocks` you get a new unproxied instance. Basically you get a `new MyClass()` here without anything AOP applied. So again your test is wrong. – M. Deinum Oct 16 '17 at 09:56
  • Why does it work good without threads? – Sviatlana Oct 16 '17 at 10:08
  • 1
    The problem with threads is they don't wait, they execute in the background. You would basically have the same problem in your live production code. Instead you should be using `@Async` and implement another way of doing the retries. – M. Deinum Oct 16 '17 at 11:39

1 Answers1

0

Probably you have to add Thread.join() after remoteDIUpdater.start() to prevent the main thread from finishing before your thread.

niemar
  • 612
  • 1
  • 7
  • 16