According to the JUnit 5 User Guide, JUnit Jupiter provides backwards compatibility for some JUnit 4 Rules in order to assist with migration.
As stated above, JUnit Jupiter does not and will not support JUnit 4 rules natively. The JUnit team realizes, however, that many organizations, especially large ones, are likely to have large JUnit 4 codebases including custom rules. To serve these organizations and enable a gradual migration path the JUnit team has decided to support a selection of JUnit 4 rules verbatim within JUnit Jupiter.
The guide goes on to say that one of the rules is ExternalResource, which is a parent for TemporaryFolder.
However, the guide unfortunately doesn't go on to say what the migration path is, or what the equivalent is for those writing new JUnit 5 tests. So what should we use?
JUnit 5.4 comes with a built-in extension to handle temporary directories in tests.
@org.junit.jupiter.api.io.TempDir
annotation can be used in order to annotate class field or a parameter in a lifecycle (e.g. @BeforeEach
) or test method of type File
or Path
.
import org.junit.jupiter.api.io.TempDir;
@Test
void writesContentToFile(@TempDir Path tempDir) throws IOException {
// arrange
Path output = tempDir
.resolve("output.txt");
// act
fileWriter.writeTo(output.toString(), "test");
// assert
assertAll(
() -> assertTrue(Files.exists(output)),
() -> assertLinesMatch(List.of("test"), Files.readAllLines(output))
);
}
You can read more on this in my blog post, where you will find some more examples on utilizing this built-in extension: https://blog.codeleak.pl/2019/03/temporary-directories-in-junit-5-tests.html.
Interesting article by author of TemporaryFolderExtension for JUnit5
and
JUnit5.0.0 is now in general release so let's hope they turn their attention to making the experimental stuff production-ready.
Meanwhile, it seems the TemporaryFolder rule will still work with JUnit5 docs
use this:
@EnableRuleMigrationSupport
public class MyJUnit5Test {
and this:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-migrationsupport</artifactId>
<version>5.0.0</version>
</dependency>
The documentation for that is still in the making - see pull request #660.
As far as I understood, there can be no one to one mapping from ExternalResource
to an equivalent in JUnit5. The concepts just don't fit. In JUnit4, the ExternalResource
basically gives you a before
and an after
callback, but within the rule, you have no control about what before
and after
actually means. You could use it with @Rule
or with @ClassRule
.
In JUnit5, the extension is defined to hook in specific extension points and thus the 'when' is well defined.
Another difference in concepts would be, that you can have a state in JUnit4 rules, but your JUnit5 extensions shouldn't have any state. Instead, all state should go to the execution context.
Nevertheless, here is an option I came along with, where before
and after
relates to each test method:
public abstract class ExternalResourceExtension
implements BeforeTestExecutionCallback, AfterTestExecutionCallback {
@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
before(context);
}
@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
after(context);
}
protected abstract void before(ExtensionContext context);
protected abstract void after(ExtensionContext context);
}
来源:https://stackoverflow.com/questions/44059317/what-is-the-equivalent-of-externalresource-and-temporaryfolder-in-junit-5