30

All tests in my test class execute a 'before' method (annotated with JUnit's @Before) before the execution of each test.

I need a particular test not to execute this before method.

Is there a way to do it?

rptmat57
  • 3,643
  • 1
  • 27
  • 38
Tomas Romero
  • 8,418
  • 11
  • 50
  • 72

8 Answers8

24

You can do this with a TestRule. You mark the test that you want to skip the before with an annotation of some description, and then, in the apply method in the TestRule, you can test for that annotation and do what you want, something like:

public Statement apply(final Statement base, final Description description) {
  return new Statement() {
    @Override
    public void evaluate() throws Throwable {
      if (description.getAnnotation(DontRunBefore.class) == null) {
        // run the before method here
      }

      base.evaluate();
    }
  };
}
Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
  • Here is the updated link: https://github.com/junit-team/junit/wiki/Rules. See also: http://junit.org/apidocs/org/junit/rules/TestRule.html – conan_z Mar 20 '15 at 17:14
  • 4
    Is there a way to easily execute the @Before statements from within the TestRule? I'm wondering what the simplest approach to the `// run the before method here` part. – loeschg Apr 09 '15 at 15:28
20

Consider using the @Enclosed runner to allow you to have two inner test classes. One with the required @Before method, the other without.

Enclosed

@RunWith(Enclosed.class)
public class Outer{

    public static class Inner1{

     @Before public void setup(){}

     @Test public void test1(){}
    }

  public static class Inner2{

   // include or not the setup
   @Before public void setup2(){}

   @Test public void test2(){}
  }

}
VLAZ
  • 26,331
  • 9
  • 49
  • 67
John B
  • 32,493
  • 6
  • 77
  • 98
13

Unfortunately you have to code this logic. JUnit does not have such feature. Generally you have 2 solutions:

  1. Just separate test case to 2 test cases: one that contains tests that require "before" running and second that contains tests that do not require this.
  2. Implement your own test running and annotate your test to use it. Create your own annotation @RequiresBefore and mark tests that need this with this annotation. The test runner will parse the annotation and decide whether to run "before" method or not.

The second solution is clearer. The first is simpler. This is up to you to chose one of them.

AlexR
  • 114,158
  • 16
  • 130
  • 208
6

This question has been asked a while ago, nevertheless, I would like to share my solution:

  1. Annotate the desired method with @Tag("skipBeforeEach")

  2. In your setup() method:

    @BeforeEach
    void setup(final TestInfo info) {
    final Set<String> testTags = info.getTags();
    if(testTags.stream()
               .filter(tag->tag.equals("skipBeforeEach"))
               .findFirst()
               .isPresent()){
    return;
    }
    // do your stuff
    }```
    
    
igor-so
  • 453
  • 9
  • 16
1

I was looking for a solution to this problem and bumped into this question. As an update, in JUnit 5 this can be easily accomplished now with the use of the @Nested annotation.

Alf
  • 1,414
  • 1
  • 15
  • 27
1

If you are using Mockito, particularly Mockito 3.0, all stubbings will be "strict" and be validated by default.

You could use the Mockito lenient() method.

More here: https://www.baeldung.com/mockito-unnecessary-stubbing-exception#lenient-stubbing

azmirfakkri
  • 571
  • 1
  • 6
  • 18
0

One can also solve this by undoing what was done in @Before setup inside test case. This is how it may look,

@Before
public void setup() {
    TestDataSetupClass.setupTestData();
}

@Test
public void testServiceWithIgnoreCommonSetup() {
    TestDataSetupClass.unSet();
    //Perform Test
}

There will be pros and cons for solutions here. Minor con for this is, unnecessary cycle of setting and un-setting step. But goes well if one needs to do it for only a test case out of hundreds and avoid overhead of writing self AOP or maintaining multiple inner test classes.

Akshay
  • 1,231
  • 1
  • 19
  • 31
0

If you have a @After method can clear the work done in @Before, you can manually call the @After method at the begining of your @Test method.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 29 '21 at 13:37