JUnit 5中ExternalResource和TemporaryFolder的对应是什么?

21
根据JUnit 5用户指南,JUnit Jupiter为了帮助迁移提供了一些对JUnit 4规则的向后兼容性。

如上所述,JUnit Jupiter不会原生支持JUnit 4规则,也不会支持。然而,JUnit团队意识到许多组织,特别是大型组织,可能拥有包括自定义规则在内的大量JUnit 4代码库。为了为这些组织提供服务并启用渐进式迁移路径,JUnit团队决定在JUnit Jupiter中逐字支持选择的JUnit 4规则。

该指南接着说其中一个规则是ExternalResource,它是TemporaryFolder的父类。
然而,该指南不幸地没有说明迁移路径是什么,或者对于编写新的JUnit 5测试的人来说等价物是什么。那么我们应该使用什么呢?
5个回答

8
有趣的一篇文章,作者是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>

6
据我所知,从ExternalResource到JUnit5中等效的映射是不可能的。这些概念根本不匹配。在JUnit4中,ExternalResource基本上为您提供了一个before和一个after回调,但在规则内部,您无法控制beforeafter的实际含义。您可以使用@Rule@ClassRule进行操作。
在JUnit5中,扩展被定义为钩入特定扩展点,因此“when”是明确定义的。
另一个概念上的区别是,在JUnit4规则中,您可以拥有状态,但是您的JUnit5扩展名不应该有任何状态。相反,所有状态都应该进入执行上下文

然而,我提供了一个选项,其中beforeafter与每个测试方法相关:

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

1
ExternalResource 之前可用于设置所有测试使用的相关对象,如果扩展无法拥有任何实例成员,那么它们如何替换此功能呢?是否有任何想法可以使扩展已经准备好的任何内容(例如 EJB 容器)能够被扩展外的代码获取到? - Alkanshel

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-tests.html


1
这个功能是实验性的,所以我不想使用它。 - dtc

4

3

现在,临时文件夹有了一种解决方案,通过@TempDir。但是,那么关于ExternalResource背后的想法呢?也许这是为了模拟数据库、模拟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() 或类似的方法,如果这是您需要的话,但出于简洁考虑,我在此省略了这部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接