Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread.sleep is not getting mocked with PowerMockito

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.

like image 709
Muku Avatar asked Nov 05 '20 05:11

Muku


People also ask

Why we will not use thread sleep method?

Thread. sleep is bad! It blocks the current thread and renders it unusable for further work.

Can we use PowerMock and Mockito together?

Mockito allows us to create mock objects. Since static method belongs to the class, there is no way in Mockito to mock static methods. However, we can use PowerMock along with Mockito framework to mock static methods.

What is PowerMockito in Java?

PowerMockito is a PowerMock's extension API to support Mockito. It provides capabilities to work with the Java Reflection API in a simple way to overcome the problems of Mockito, such as the lack of ability to mock final, static or private methods.

What is sleep method in multithreading?

Thread. sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system.


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
like image 97
Michael Easter Avatar answered Oct 13 '22 00:10

Michael Easter