Thread.sleep 没有被 PowerMockito 嘲笑

Muk*_*uku 8 java junit multithreading mocking powermockito

这是我的设置不起作用:

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();
}
Run Code Online (Sandbox Code Playgroud)

某个类.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) {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是 PowerMockitoThread.sleep()在实际被调用时不是在嘲笑它,Someclass而是Thread.sleep()在 JUnit 本身内部被调用时奇怪地工作。

我知道Thread.sleep()用另一种方法包装可以解决我的问题,但我只想知道Thread.sleep()使用 PowerMockito 进行模拟的正确方法。

Mic*_*ter 3

工作示例在这里。请注意,这集中于“如何模拟Thread.sleep”,并不包括示例中的所有原始代码。(我不确定您的示例是否足够完整以准确重现。)

如果“正在测试”的类看起来像这样(我们记录 的经过时间Thread.sleep):

编辑:请注意,空catch (Exception ex)块现在将记录一条消息)。

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++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后考虑以下测试:

@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(); 
    }
}
Run Code Online (Sandbox Code Playgroud)

如果没有模拟,测试将花费约 15 秒(因为代码将休眠 5 秒,共 3 次),但是使用模拟,输出为:

TRACER caught exception: mock error
TRACER caught exception: mock error
TRACER caught exception: mock error
Run Code Online (Sandbox Code Playgroud)