I have a basic test class from which all of my other test cases inherit from.
In the superclass, I have a global timer set via:
@Rule
public Timeout globalTimeout = new Timeout(30000);
However, for certain methods in the sub-classes I would like the timeout to be longer.
For example:
@test(timeout=alongtime)
private void sometTest()
But this doesn't seem to affect the global timer at all, which I tested by setting a very short timeout globally, and a very long timeout in the sub-class.
Is there a way to have JUnit honor a timeout defined on a method?
The TestName Rule Put simply, the TestName rule provides the current test name inside a given test method: In this trivial example, when we run the unit test, we should see the test name in the output: INFO c.baeldung.rules.JUnitRulesUnitTest - Executing: givenAddition_whenPrintingTestName_thenTestNameIsDisplayed 5.4. The Timeout Rule
JUnit 4 rules provide a flexible mechanism to enhance tests by running some code around a test case execution. In some sense, it’s similar to having @Before and @After annotations in our test class. Let's imagine we wanted to connect to an external resource such as a database during test setup and then close the connection after our test finishes.
Sometimes you use more than one rule in a test case. If for some reason you have to define an order of how these rules are nested at runtime, JUnit offers the type RuleChain. This class provides the methods outerRule and around to configure an execution chain of TestRule s in a fluent interface like style.
The statement represents our tests within the JUnit runtime. When we call the evaluate () method, this executes our test. In this example, we log a before and after message and include from the Description object the method name of the individual test. 8. Using Rule Chains
Apparently there is an open issue in jUnit project here and it seems they are thinking to refactor the whole concept of Timeout in the project.
But in the meantime I was looking for the same thing and found this post which does not use the Timeout
rule but another one which is like a workaround.
For example in my case I have some backed who are fast and some other who are slow, I just created the Watcher with two different timeout:
@Rule
public TestWatcher watcher = new TestWatcher() {
@Override
public Statement apply(Statement base, Description description) {
if (description.getMethodName().toLowerCase().contains("slow")) {
return new FailOnTimeout(base, 15000);
} else {
return new FailOnTimeout(base, 5000);
}
}
};
This is clearly not the solution ready for everybody (depending how you named your tests as well) but I found it interesting, especially when using the jUnit framework in "Integration Testing" or in "Continuous Integration" environments.
UPDATE:
I found a better approach: use a specific custom annotation for the slow requests:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SlowRequest {
// Just for tagging a method and adapt the timeout
}
and the Watcher code would be:
if (description.getAnnotation(SlowRequest.class) != null) {
return new FailOnTimeout(base, 60000);
} else {
return new FailOnTimeout(base, 25000);
}
and in the Tests, just use it like this:
@Test
@SlowRequest
public void testSlowMethod() {
// slow test here
}
I have a basic test class from which all of my other test cases inherit from.
Don't do that.
Using inheritance to share test code isn't very flexible. Use delegation to share code. In this case, just add the timeout rule to the test classes that need it. Most of your tests should be unit tests and shouldn't need a timeout.
If you have a lot of logic in your base class, extract it out to another class (possibly a custom rule).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With