简体   繁体   中英

Unable to test java.util.Timer using Junit along with CountDownLatch

I am using a timer to perform some operation repetitively every 2 seconds. I am using JUnit to test this timer method.

Normally if I call the timer method, it just runs once and exits without giving me the actual results. But if I use the CountDownLatch, I get the expected result but the test never terminates or passes, it keeps on waiting for something even though the expected result is already obtained.

Is there a way to get around this problem or cancelling the CountDownLatch after some criterion is met?

Below is my code for the timer class and the JUnit test:

public class TimerTest {
int count=0;    
private  Timer timer = new Timer();     

void doSomething() {  
    timer.schedule(new TimerTask() {
        public void run() {
            doSomethingElse();  
        }
    },
    1000, 2000);   

}

private  void doSomethingElse(){
    count++;
    System.out.println("the count is "+count);
    if(count>5){
        timer.cancel();
        timer.purge();
    }


}

}

Below is the Junit:

public class JunitTimer {
@Test
public void test() throws InterruptedException {


     TimerTest test = new TimerTest();
     final CountDownLatch latch = new CountDownLatch(2);        
   test.doSomething();
   latch.countDown();


   System.out.println("LCountdown is " +latch.getCount());
    latch.await();


}
}

Try to use ScheduledExecutorService which is injected into your class, so that you could inject mock into it while testing. The real app would inject real executor.

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.SECONDS;

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class DatabasePoller
{
    private final ScheduledExecutorService scheduler;
    private int count = 0;
    private volatile ScheduledFuture<?> scheduled;

    public DatabasePoller(final ScheduledExecutorService scheduler)
    {
        this.scheduler=scheduler;
    }

    void doSomething()
    {
        Runnable runnable = new Runnable() {
            public void run() {
                doSomethingElse();
            }
        };
        scheduled = scheduler.scheduleAtFixedRate(runnable, 1, 2, SECONDS);
    }

    private void doSomethingElse()
    {
        ++count;
        // do something useful
        if(count > 5) scheduled.cancel(false);
    }
}

public class DatabasePollerTest {
    @InjectMocks
    DatabasePoller testObject;
    @Mock
    ScheduledExecutorService scheduler;
    @Mock
    ScheduledFuture scheduled;
    @Captor
    ArgumentCaptor<Runnable> runnableCaptor;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        when(scheduler.scheduleAtFixedRate(runnableCaptor.capture(), anyInt(), anyInt(), any(TimeUnit.class)))
                .thenReturn(scheduled);
    }
    @Test
    public void testDoSomething() throws Exception {

        testObject.doSomething();

        Runnable runnable = runnableCaptor.getValue();

        // schedule is not cancelled if invoked five times
        for(int i=1; i<=5; ++i)
            runnable.run();
        verify(scheduled, never()).cancel(anyBoolean());

        // sixth time should cancel scheduled task
        runnable.run();
        verify(scheduled, times(1)).cancel(false);
    }
}

Thank you for the help. In the mean time I have found a much simpler and easy solution to this problem; below is the solution to my problem:

public class RepeatTest {
boolean repeat=true;
Integer count=0;
public boolean returncount(){

        count++;
        System.out.println("the count is"+count);
        if(count.equals(5)){
            repeat=false;
        }

    return repeat;
}

@Test
public void testreturn() throws InterruptedException{
    boolean flag=returncount();
    while(flag){
        flag=returncount();
        Thread.sleep(4000);
    }
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM