Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUnit @Rule lifecycle interaction with @Before

I have some JUnit tests that use the TemporaryFolder @Rule. They use the TemporaryFolder in a @Before method to perform some setup:

@Rule
public TemporaryFolder folder = new TemporaryFolder();

@Before
public void init() {
  folder.newFile("my-file.txt");
}

@Test
public void myTest() { ... }

Most of the time this works perfectly. However, when using the SpringJUnit4ClassRunner I find that in some cases the init() method is invoked before the Statement inside my TemporaryFolder instance is applied. Because of this, the temporary folder location is unset (i.e: null) when folder is used within init() and my file ends up in the working directory, not /tmp.

So in some cases @Before methods are executed ahead of the rules, however, I can't establish a definite pattern. I occasionally see a similar problem with some of my own rule implementations.

Is there any way that I can ensure that my rule statements are applied before any setup methods?

like image 836
teabot Avatar asked Oct 12 '11 10:10

teabot


1 Answers

In JUnit 4.10, BlockJUnit4ClassRunner (the superclass of SpringJUnit4ClassRunner) appears to take care to construct Statement chains in such a way that rules run before any @Before methods. From JUnit 4.10:

protected Statement methodBlock(FrameworkMethod method) {
    // ...
    Statement statement= methodInvoker(method, test);
    statement= possiblyExpectingExceptions(method, test, statement);
    statement= withPotentialTimeout(method, test, statement);
    statement= withBefores(method, test, statement);
    statement= withAfters(method, test, statement);
    statement= withRules(method, test, statement);
    return statement;
}

JUnit 4.7 appears to stitch Statement chains together in a different order:

Statement statement= methodInvoker(method, test);
statement= possiblyExpectingExceptions(method, test, statement);
statement= withPotentialTimeout(method, test, statement);
statement= withRules(method, test, statement);
statement= withBefores(method, test, statement);
statement= withAfters(method, test, statement);
return statement;

spring-test-3.0.5's parent POM seems to indicate that it depends on JUnit 4.7. I wonder if getting it to use a newer JUnit would help?

like image 161
pholser Avatar answered Oct 16 '22 04:10

pholser