Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUnit test for an expected timeout

I have a test of communication over a TCP socket where I expect the server to not respond within a set time frame when I send a certain message.

The servers behaviour is nothing I can control.

I know how to fail a test if it has not completed within a set time frame. But how can I do the opposite, make it pass for not completing within the timeframe?

I can use @Test (timeout=1000) to make a test fail if not complete within a second.

But, using Junit 4, is there a function to test for an expected timeout as a positive result? I.e. The test will fail if completed within the time frame and pass if not?

like image 224
Einar Sundgren Avatar asked May 20 '16 20:05

Einar Sundgren


People also ask

How will you set the timeout in test cases in JUnit?

To specify the timeout period of a certain test case, “timeout” attribute is mentioned on the annotation @Test . Note that the timeout time is specified in milliseconds. In the above test, execution will be timed out after 500ms with the below message.

How do I use timeout in JUnit?

JUnit provides a handy option of Timeout. If a test case takes more time than the specified number of milliseconds, then JUnit will automatically mark it as failed. The timeout parameter is used along with @Test annotation. Let us see the @Test(timeout) in action.

What does @test timeout 1000 annotation does in JUnit framework?

Annotations for Junit testing @Test(timeout=1000) annotation specifies that method will be failed if it takes longer than 1000 milliseconds (1 second).

What is timeout JUnit?

@Timeout is used to define a timeout for a method or all testable methods within one class and its @Nested classes. This annotation may also be used on lifecycle methods annotated with @BeforeAll , @BeforeEach , @AfterEach , or @AfterAll .


2 Answers

Good question. Actually you can do this using only junit tools. My idea is to inverse Timeout rule behaviour + use expected attribute of Test annotation. The only one limitation: you have to place your test in separate class, because Rule applies to all tests inside it:

public class Q37355035 {

    private static final int MIN_TIMEOUT = 100;

    @Rule
    public Timeout timeout = new Timeout(MIN_TIMEOUT) {
        public Statement apply(Statement base, Description description) {
            return new FailOnTimeout(base, MIN_TIMEOUT) {
                @Override
                public void evaluate() throws Throwable {
                    try {
                        super.evaluate();
                        throw new TimeoutException();
                    } catch (Exception e) {}
                }
            };
        }
    };

    @Test(expected = TimeoutException.class)
    public void givesTimeout() throws InterruptedException {
        Thread.sleep(1000);
    }
}
like image 56
Andremoniy Avatar answered Sep 22 '22 19:09

Andremoniy


I'm building upon the great answer by Andremoniy, don't forget to upvote his answer if you like this one!

I used the following modification to skip a test if it doesn't finish in the expected time frame. The benefit of this is that the test will be marked as Skipped by JUnit instead of Successful. This is good for optimistic execution of tests which can sometimes hang or not finish fast enough, but you don't want to mark them as failed or delete them.

public class OptimisticTestClass {

    private static final int TEST_METHOD_TIMEOUT_MS = 100;

    @Rule
    public Timeout timeout = new Timeout(TEST_METHOD_TIMEOUT_MS, TimeUnit.MILLISECONDS) {
        public Statement apply(Statement base, Description description) {
            return new FailOnTimeout(base, TEST_METHOD_TIMEOUT_MS) {
                @Override
                public void evaluate() throws Throwable {
                    try {
                        super.evaluate();
                    } catch (TestTimedOutException e) {
                        Assume.assumeNoException("Test did not finish in the allocated time, skipping!", e);
                    }
                }
            };
        }
    };

    // The test times out and is skipped
    public void givesTimeout() throws InterruptedException {
        Thread.sleep(1000);
    }
}
like image 34
JohnEye Avatar answered Sep 21 '22 19:09

JohnEye