3

High level, I have JUnit test class which is pretty straightforward. I have several @Tests and a single @Before which does some set up. For one test case, the setup varies (I don't want it to be run).

From some searching I found https://stackoverflow.com/a/13017452/413254. This suggests creating a @Rule which checks for a particular annotation and executes the @Before statement.

My confusion is around how to execute the @Before method in the rule. Is there a way to do that? Or do I need to pass in the test class itself and execute the @before method (setup() in the example below)?

public class NoBeforeRule implements TestRule {

    @Override
    public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                if (description.getAnnotation(NoBefore.class) == null) {
                    // Is there something like `base.executeAllTheBefores()' 
                }

                base.evaluate();
            }
        };
    }
}

The relevant test code:

@Rule public NoBeforeRule mNoBeforeRule = new NoBeforeRule(this);

@Before
@Override
public void setup() {
}

@Test
public void testNeedSetup() {
    // this should run setup()
}

@NoBefore
@Test
public void testNoSetup() {
    // this should NOT run setup()
}
Community
  • 1
  • 1
loeschg
  • 29,961
  • 26
  • 97
  • 150

3 Answers3

3

Why don't you just split the tests into 2 separate test classes? The ones that need the setup go into one class and the one(s) that don't go into another.

There is no rule (or even guideline) that states all the tests for a class must go into a single test class, and this is in fact something I do very often.

The fact you have a single or multiple tests that don't need the common setup is probably an indication that the tests themselves aren't cohesive and are testing a different variation of your class under test. For example, I may have a bunch of methods that have a mock setup in a specific way for positive tests, but then other tests that need it configured differently for failure scenarios. I will move these tests into 2 classes - specifically the ones for positive scenarios and ones for failure scenarios.

Playing around with Rules and such-like to explicitly avoid running the standard @Before method will just make things more complicated and have your future-self or colleagues scratching their heads as to why the setup method isn't being run

tddmonkey
  • 20,798
  • 10
  • 58
  • 67
1
  • call setup() in the custom rule implementation.

  • remove the @Before annotation on setup(), as including the @Rule will cause the custom rule to be run each time.

    public class MyTest {
    
       class NoBeforeRule implements TestRule {
          @Override
          public Statement apply(final Statement base, final Description description) {
              return new Statement() {
                  @Override
                  public void evaluate() throws Throwable {
                      if (description.getAnnotation(NoBefore.class) == null) {
                          setup(); 
                      }
    
                      base.evaluate();
                  }
              };
          }
       }
    
       @Rule 
       public NoBeforeRule mNoBeforeRule = new NoBeforeRule();
    
    
       public void setup() {}
    
       @Test
       public void testNeedSetup() {
          // this should run setup()
       }
    
       @NoBefore
       @Test
       public void testNoSetup() {
          // this should NOT run setup()
       }
    }
    
arvindkgs
  • 373
  • 4
  • 12
0

Maybe play around with the rule TestName

@Rule public TestName name = new TestName();

@Before 
public void setup() {
     if(listOfTestNeedSetup.contains(name.getMethodName()) {
        // need setup
     }
}
Peter
  • 5,556
  • 3
  • 23
  • 38
  • 1
    where is the initialization of `listOfTestNeedSetup`?, or how to?, can you add that to make this answer more relevant, else this looks like a partial answer to me. – Hiren Aug 15 '18 at 18:15