19

根据JUnit 5 User Guide,JUnit Jupiter 为一些 JUnit 4 规则提供向后兼容性以帮助迁移。

如上所述,JUnit Jupiter 本身不会也不会支持 JUnit 4 规则。然而,JUnit 团队意识到,许多组织,尤其是大型组织,可能拥有包括自定义规则在内的大型 JUnit 4 代码库。为了服务这些组织并实现逐步迁移路径,JUnit 团队决定在 JUnit Jupiter 中逐字支持选择 JUnit 4 规则。

该指南继续说,其中一个规则是ExternalResource,它是TemporaryFolder的父级。

但是,不幸的是,该指南没有继续说明迁移路径是什么,或者对于那些编写新的 JUnit 5 测试的人来说是什么等价物。那么我们应该使用什么呢?

4

5 回答 5

7

JUnit5 的 TemporaryFolderExtension 作者的有趣文章

他在 github 上的代码仓库

JUnit5.0.0 现已全面发布,因此我们希望他们将注意力转向使实验性的东西可以投入生产。

同时,似乎 TemporaryFolder 规则仍然适用于 JUnit5文档

用这个:

@EnableRuleMigrationSupport
public class MyJUnit5Test {

还有这个:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-migrationsupport</artifactId>
    <version>5.0.0</version>
</dependency>
于 2017-09-15T10:16:13.490 回答
6

据我了解,ExternalResource在 JUnit5 中没有从到等价物的一对一映射。只是概念不合适。在 JUnit4 中,ExternalResource基本上给你一个before和一个after回调,但在规则内,你无法控制什么beforeafter实际意味着什么。您可以将它与@Rule或 一起使用@ClassRule

在 JUnit5 中,扩展被定义为挂钩特定的扩展点,因此“何时”定义得很好。

概念上的另一个区别是,您可以在 JUnit4 规则中有一个状态,但您的 JUnit5 扩展不应该有任何状态。相反,所有状态都应该转到执行上下文

尽管如此,这是我带来的一个选项,在哪里before以及after与每种测试方法相关:

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);
}
于 2017-10-04T04:57:14.853 回答
5

JUnit 5.4 带有一个内置扩展来处理测试中的临时目录。

@org.junit.jupiter.api.io.TempDir注释可用于注释类字段或生命周期中的参数(例如)或类型或@BeforeEach测试方法。FilePath

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))
    );
}

您可以在我的博客文章中阅读更多关于此内容的信息,您将在其中找到更多使用此内置扩展的示例:https ://blog.codeleak.pl/2019/03/temporary-directories-in-junit-5-测试.html

于 2019-03-18T21:53:49.020 回答
4

相关文档仍在制作中 - 请参阅pull request #660

于 2017-05-19T08:30:57.127 回答
3

临时文件夹现在有了@TempDir. ExternalResource但是,一般来说,s背后的想法呢?也许它是用于模拟数据库、模拟 HTTP 连接或您想要添加支持的其他一些自定义资源?

答案是,你可以使用@RegisterExtension注释来实现非常相似的东西。

使用示例:

/**
 * This is my resource shared across all tests
 */
@RegisterExtension
static final MyResourceExtension MY_RESOURCE = new MyResourceExtension();

/**
 * This is my per test resource
 */
@RegisterExtension
final MyResourceExtension myResource = new MyResourceExtension();

@Test
void test() {
    MY_RESOURCE.doStuff();
    myResource.doStuff();
}

这是基本的脚手架MyResourceExtension

public class MyResourceExtension implements BeforeAllCallback, AfterAllCallback,
        BeforeEachCallback, AfterEachCallback {

    private SomeResource someResource;

    private int referenceCount;

    @Override
    public void beforeAll(ExtensionContext context) throws Exception {
        beforeEach(context);
    }

    @Override
    public void afterAll(ExtensionContext context) throws Exception {
        afterEach(context);
    }

    @Override
    public void beforeEach(ExtensionContext context) throws Exception {
        if (++referenceCount == 1) {
            // Do stuff in preparation
            this.someResource = ...;
        }
    }

    @Override
    public void afterEach(ExtensionContext context) throws Exception {
        if (--referenceCount == 0) {
            // Do stuff to clean up
            this.someResource.close();
            this.someResource = null;
        }
    }

    public void doStuff() {
        return this.someResource.fooBar();
    }

}

你当然可以将这一切包装为一个抽象类,并MyResourceExtension实现只是protected void before()protected void after()或一些这样的,如果那是你的事,但为了简洁起见,我省略了。

于 2019-12-24T08:02:14.723 回答