Testing Interrupts
It can be tricky to test that an interrupt has been called on a thread because of the possibility of race conditions between calling interrupt
and checking the status of the interrupt flag using Thread.isInterrupted()
or Thread.interrupted
. For example, the interrupt status can be reset when a thread goes into the TERMINATED
state. You can use the WaitFor
class to express an assertion must be true within a given time (as below) but in this case, the race conditions can still occur (due to the frequency of the check whilst waiting). In the example below, the created thread will perform some blocking function that can be interrupted (for example, sleeping) and we're testing that the call to interrupt
will wake and change the interrupt status flag (asserting against thread.isInterrupted
).
1 2 3 4 5 6 7 8 9 10 11 12 |
|
It may be simpler to use a stub to capture the interrupt. The InterruptCapturingThread
class of tempus-fugit is just a stub extending Thread
which records and gives access to stack traces of threads that call interrupt
on it.
1 2 3 4 5 6 7 8 9 |
|
For testing purposes, you can also get a view on the stack traces of the threads that called interrupt
on your thread. Calling thread.printStackTraceOfInterruptingThreads(System.out)
from the example above would show something like the following.
java.lang.Thread.getStackTrace(Thread.java:1409)
com.google.code.tempusfugit.concurrency.InterruptCapturingThread.interrupt(InterruptCapturingThread.java:61)
com.google.code.tempusfugit.concurrency.InterruptCapturingThreadTest.interrupted(InterruptCapturingThreadTest.java:39)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:585)
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
org.junit.internal.runners.statements.FailOnTimeout$1.run(FailOnTimeout.java:28)