Thread.sleep is not getting mocked with PowerMockito

Viewed 1346

Here's my setup which is not working:

SomeclassTest.java

@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PrepareForTest({SomeclassTest.class, Someclass.class})
public class SomeclassTest{

@InjectMocks
private Someclass someclass;

@Test(expected=None.class)
public void testRun() throws Exception{     
    PowerMockito.mockStatic(Thread.class);
    PowerMockito.doThrow(new RuntimeException()).when(Thread.class);
    Thread.sleep(Matchers.anyLong());        
    try {
            Thread.sleep(5L);
    }catch(Exception ex) {
            System.out.println("working"); // this is working
    }    
    WhiteboxImpl.invokeMethod(someclass, "run"); // not working in someclass
    PowerMockito.verifyStatic();
}

Someclass.java

@Named("Someclass")
public class Someclass extends Thread{

@Override
public void run() {
    while (true) {
        try {
            // clear interruption
            interrupted(); 
            
            long noOfRec= 0;
            if (noOfRec> 0) {
                Thread.sleep(shortInterval);
            } else {
                Thread.sleep(longInterval);
            }
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt(); 
        } catch (Exception ex) {
        }
    }
}

My issue is PowerMockito isn't mocking Thread.sleep() when it's actually called in Someclass but weirdly working when Thread.sleep() is called inside the JUnit itself.

I am aware that wrapping Thread.sleep() in another method will solve my issue but I just want to know the correct method of mocking Thread.sleep() with PowerMockito.

1 Answers

Working example here. Note that this concentrates on "how to mock Thread.sleep" and does not include all of the original code in your example. (I'm not sure that your example is complete enough to reproduce exactly.)

If the class "under test" looks like this (where we log the elapsed time of Thread.sleep):

(Edit: note that the empty catch (Exception ex) block will now log a message).

public class SomeClass extends Thread {
    private long shortInterval = 100;
    private long longInterval = 5000;

    @Override
    public void run() {
        // original code had `while (true)` but this is simpler as an illustration:
        int counter = 0;
        while (counter < 3) {
            try {
                // clear interruption
                interrupted(); 
                
                long noOfRec = 0;
                if (noOfRec > 0) {
                    Thread.sleep(shortInterval);
                } else {
                    // in addition to Thread.sleep, log the elapsed time 
                    long startTime = System.nanoTime();    
                    Thread.sleep(longInterval);
                    long elapsedInNanos = System.nanoTime() - startTime;
                    long elapsedInSeconds = TimeUnit.SECONDS.convert(elapsedInNanos, TimeUnit.NANOSECONDS);
                    System.out.println(String.format("TRACER elapsed in seconds: %d", elapsedInSeconds));
                }
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); 
            } catch (Exception ex) {
                System.out.println("TRACER caught exception: " + ex.getMessage());
            }

            counter++;
        }
    }
}

then consider the following test:

@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@PrepareForTest({SomeClass.class, Thread.class})
public class SomeClassTestCase {

    @Test(expected=Test.None.class)
    public void testRun() throws Exception {     
        PowerMockito.mockStatic(Thread.class);
        PowerMockito.doThrow(new RuntimeException("mock error")).when(Thread.class);
        Thread.sleep(Matchers.anyLong()); 

        SomeClass someClass = new SomeClass();
        
        // test
        someClass.run(); 
    }
}

Without mocks, the test will take ~15 seconds (since the code will sleep for 5 seconds, three times), but with mocks, the output is:

TRACER caught exception: mock error
TRACER caught exception: mock error
TRACER caught exception: mock error
Related