Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to override a junit rule in a subclassed test script?

Tags:

java

junit

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?

like image 871
user3308774 Avatar asked Mar 26 '14 16:03

user3308774


People also ask

What is testname rule in JUnit?

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

What are @JUnit 4 rules?

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.

What is the rulechain class In JUnit?

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.

Which statement represents a test within the JUnit runtime?

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


2 Answers

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
}
like image 175
рüффп Avatar answered Oct 06 '22 22:10

рüффп


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).

like image 22
NamshubWriter Avatar answered Oct 06 '22 21:10

NamshubWriter