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.