My Junit version is 4.12
#Test
public void test()throws InterruptException{
doSomething();
Thread.sleep(1000);
AssertResult();
}
When I run mvn test. I got a InterruptException.But when i run with ItelliJ Idea, this case will pass.
Even if I add timeout to my test case like this,I still got a InterruptException.
#Test(timeout=10000)
public void test()throws InterruptException{
doSomething();
Thread.sleep(1000);
AssertResult();
}
Then i add a method realSleep to process it.Then case passed.But I think it not a graceful solution.
public static void realSleep(long time){
long start = System.currentTimeMills();
while(true){
try{
Thread.sleep(time)
}catch(InterruptedException e){
}
if(System.currentTimeMills()-start>time){
return
}
}
}
Related
How to test an exception in the run function?
` public void run() {
ArrayBlockingQueue<String> bookQueue =
library.getBookQueue(book);
try {
bookQueue.take();
try {
updateState(State.IN_PROGRESS);
Thread.sleep(READ_TIME_MS);
bookQueue.put(book);
updateState(State.ENDED);
} catch(InterruptedException e){
bookQueue.put(book);
}
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
finally {
updateState(State.ENDED);
}
}`
In the #Test annotation you can specify the expected exception
For Example
#Test(expected=IndexOutOfBoundsException.class)
public void outOfBounds() {
new ArrayList<Object>().get(1);
}
In the same way you can write test method and call run method inside of it
#Test(expected=Exception.class)
public void testRun() {
run();
}
We can also make this better by considering the #GhostCatsuggestions in the comments, you can addtry-catch` in test method
#Test
public void testRun() {
tyr {
run();
Asserts.fail(); //
}
catch(Exception ex) {
assertTrue(//some condition);
assertEquals(//some condition);
}
}
If run() method doesn't throw any exception test will fail because of Asserts.fail(), or in any exception case catch block assert statements will get executed
Let's say I have method like this:
public int toTest() {
try { Thread.sleep(60 * 1_000); }
catch (InterruptedException ignored) {}
return 8;
}
And I would like to test it e.g. check if returned value is correct, like this:
#Test
public void test() {
int actual = toTest();
assertThat(actual).isEqualTo(8);
}
Is there any way to "simulate" time lapse so during test execution I will not be force to wait for whole minute?
Edit:
Probably I described my question too concrete. I didn't want to focus on this exact one minute but on way to bypass it. There could be even 100 days but my question is if there is method to simulate this time lapse.
Like in project reactor methods with are using virtual time https://projectreactor.io/docs/test/snapshot/api/reactor/test/StepVerifier.html#withVirtualTime-java.util.function.Supplier-
You can achieve that using Powermock.
// This will mock sleep method
PowerMock.mockStatic(Thread.class, methods(Thread.class, "sleep"));
PowerMockito.doThrow(new InterruptedException()).when(Thread.class);
Thread.sleep(Mockito.anyLong());
At the start of class, you will need to add this
#PrepareForTest(YourClassToWhich_ToTest_MethodBelong.class)
JUnit test the method as is (unless you add mocking..) if you want you can test internal method as toTestInternal:
public int toTest() {
try { Thread.sleep(60 * 1_000); }
catch (InterruptedException ignored) {}
return toTestInternal();
}
public int toTestInternal() {
return 8;
}
and test the method you want (toTestInternal):
#Test
public void test() {
int actual = toTestInternal();
assertThat(actual).isEqualTo(8);
}
I would suggest to make the interval a dynamic parameter. It will save your time:
public int toTest(int interval) {
try {
Thread.sleep(interval);
}catch (InterruptedException ignored) {}
return 8;
}
and the test class to be like:
#Test
public void test() {
int actual = toTest(60);
assertThat(actual).isEqualTo(8);
}
In Intelij and Eclipse IDEs (and probably some others too) it's possible to run all test classes from a package (or even all test classes in a project) without the need to put each of them explicitly in a test suite class (this is something I want to avoid). Just right click -> run all tests and voilĂ !
I've got one problem with that approach to testing though. I want to do some cleaning up after all the tests are done, but no matter what I do, nothing seems to work.
At first, I tried using RunListener and its testRunFinished() method, but it is called after every atomic test is done, so not what I want when running many of them.
Then I thought about finalizers and runFinalizersOnExit(true), unfortunatelly, it is deprecated and worked only on one of computers that tests are executed on.
Last thing I tried was to create a "listener" thread, that - given tests execution start and end time differences - would clean up, for instance, after five seconds of test completion. I used code below to test that solution:
import org.junit.Test;
public class Main {
static {
System.out.println("In a static block!");
new Thread(new Runnable() {
public void run() {
System.out.println("Starting static thread!");
try {
while (true) {
Thread.sleep(1000);
System.out.println("Static thread working...");
}
} catch (InterruptedException e) {
System.err.println("Static thread interrupted!");
e.printStackTrace();
} catch (Exception e) {
System.err.println("Static thread catches exception!");
e.printStackTrace();
} finally {
System.err.println("Static thread in finally method.");
Thread.currentThread().interrupt();
}
}
}).start();
System.out.println("Exiting static block!");
}
#Test
public void test() throws Exception {
System.out.println("Running test!");
Thread.sleep(3000);
System.out.println("Stopping test!");
}
}
With no luck. The thread is killed after the test is done. And even the finally block is never executed...
In a static block!
Exiting static block!
Running test!
Starting static thread!
Static thread working...
Static thread working...
Stopping test!
Static thread working...
Desired behavior would be:
right click
run all tests
TestA is running...
TestA done
TestB is running...
TestB done
... more test classes...
cleanup
Not sure if I fully have your question right, but I think you want before, beforeClass, after and afterClass methods. i.e.
#BeforeClass
public void beforeClass() {
// Do stuff before test class is run
}
#Before
public void before() {
// Do stuff before each test is run
}
#After
public void after() {
// DO stuff after each test is run
}
#AfterClass
public void afterClass() {
// DO stuff after test class is run
}
You can do things on a more global level with some hacking or other frameworks. Spring's test suites for example. But I would try to keep such things within the scope of a single test class.
I've found a solution to my problem. My colleague suggested "hey, can't you just count the test classes?" - and that's what I did.
A little bit of reflection magic is used here, so the code might not be portable:
public abstract class CleaningTestRunner extends BlockJUnit4ClassRunner {
protected abstract void cleanupAfterAllTestRuns();
private static long TEST_CLASSES_AMOUNT;
private static long TEST_RUNS_FINISHED = 0;
private static boolean CLASSES_COUNTED = false;
static {
while (!CLASSES_COUNTED) {
try {
Field f = ClassLoader.class.getDeclaredField("classes");
f.setAccessible(true);
Vector<Class> classes = (Vector<Class>) f.get(CleaningTestRunner.class.getClassLoader());
TEST_CLASSES_AMOUNT = 0;
for (Class<?> klass : classes) {
if (klass.isAnnotationPresent(RunWith.class)) {
if (CleaningTestRunner.class.isAssignableFrom(klass.getAnnotation(RunWith.class).value())) {
for (Method method : klass.getMethods()) {
if (method.isAnnotationPresent(Test.class)) {
++TEST_CLASSES_AMOUNT;
break;
}
}
}
}
}
CLASSES_COUNTED = true;
} catch (Exception ignored) {
}
}
}
public CleaningTestRunner(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
public void run(RunNotifier notifier) {
notifier.addListener(new TestCleanupListener());
super.run(notifier);
}
private class TestCleanupListener extends RunListener {
#Override
public void testRunFinished(Result result) throws Exception {
++TEST_RUNS_FINISHED;
if (TEST_RUNS_FINISHED == TEST_CLASSES_AMOUNT) {
cleanupAfterAllTestRuns();
}
}
}
}
I have a class with a method that blocks and would like to validate that it is blocking. The method is as shown below.
public static void main(String[] args) {
// the main routine is only here so I can also run the app from the command line
applicationLauncherInstance.initialize();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
if (null != application) {
applicationLauncherInstance.terminate();
}
}
});
try {
_latch.await();
} catch (InterruptedException e) {
log.warn(" main : ", e);
}
System.exit(0);
}
How can I write a unit test for such a method. I am stuck before starting.
public class ApplicationLauncherTest extends TestCase {
public void testMain() throws Exception {
ApplicationLauncher launcher = new ApplicationLauncher();
}
}
Thanks to Kulu, I found the solution.
public void testMain() throws Exception {
Thread mainRunner = new Thread(() -> {
ApplicationLauncher.main(new String[]{});
});
mainRunner.start();
Thread.sleep(5000);
assertEquals(Thread.State.WAITING, mainRunner.getState());
mainRunner.interrupt();
}
Bwire's answer is a good way there, but I highly recommend that no
one ever use Thread.sleep() in unit tests for validation of some situation. It's impossible to get the timing right:
If it's too short, you'll get a lotta false results (random failures, yay)
If it's too long, you end up creating painfully slow tests over time. Don't underestimate this.
So, what's the answer? Any time you need to "sleep" to test something, instead "wait" for that to be true (constantly checking). This way:
As soon as the condition is true, your program resumes--no wasted time.
You can set the timeout on this "wait" to a crazy large value, to avoid random failures.
Here's a modified version of Bware's self-response...
public void testMain() throws Exception {
Thread mainRunner = new Thread(() -> {
ApplicationLauncher.main(new String[]{});
});
mainRunner.start();
expectToBlock(mainRunner, 30, TimeUnit.SECONDS);
mainRunner.interrupt();
}
private static void expectToBlock(Thread thread, long waitCount, TimeUnit waitUnits) {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < waitUnits.toMillis(waitCount)) {
if (thread.getState() == Thread.State.WAITING) {
return;
}
Thread.sleep(50); // Don't hog the CPU
}
Assert.fail("Timed out while waiting for thread to block");
}
#Test (expected=TimeoutException.class,timeout=1000)
public void fineForFiveSeconds() {
foo.doforever();
fail("This line should never reached");
}
This is my test code.
All I want is to run doforever() for some time period then make the test succeed.
Try this:
Execute the logic in a thread, sleep and check if the thread is still alive.
#Test
public void fineForFiveSeconds() throws InterruptedException {
Thread thread = new Thread() {
#Override
public void run() {
foo.doforever();
}
};
thread.start();
//Let the current thread sleep (not the created thread!)
Thread.sleep(5000);
assertTrue(thread.isAlive());
}