如何在JUnit 5中替换WireMock的@Rule注解?

100

我在测试中使用WireMock,并有这样一行代码:

@Rule
public WireMockRule wireMockRule = new WireMockRule(8080);

我想转换到JUnit 5。因此,我添加了以下依赖项(使用Gradle):

testCompile('org.junit.jupiter:junit-jupiter-engine:5.1.1')

但是在尝试导入@Rule注释时没有建议。

我需要添加另一个JUnit依赖模块吗?或者JUnit 5不支持规则吗?如果不支持,我该如何替换@Rule注释以使测试重新工作?


请查看这篇不错的文章:https://www.codeaffine.com/2016/04/06/replace-rules-in-junit5/ - Ivan Gammel
没有直接的替代方案,Junit Jupiter使用@Extension而不是@Rule;开发人员需要移植他们的代码 - WireMock还没有完成这个工作(https://github.com/tomakehurst/wiremock/issues/684)。您可以自己实现一个`@Extension`。 - Boris the Spider
5个回答

57
一般来说,JUnit 4 中使用 @Rule@ClassRule 的内容应该使用 JUnit 5 中的 @ExtendWithExtension 来完成,它们提供了与 JUnit 4 中非常相似的功能。
它作为标准的 JUnit 生命周期钩子,但是它被提取到一个Extension类中。类似于 @Rule,测试类可以添加任意数量的 Extension
处理这个问题有几种可能的方法:
  • 保持 JUnit 4 的方式(JUnit 5 拥有 JUnit Vintage 部分,可以执行 JUnit 3 或 4 的测试)。
  • @Rule 重写为 Extension
  • 在每个测试类中使用 @BeforeEach@AfterEach 钩子方法实现 WireMockRule 所做的实际处理(启动服务器、执行测试并停止服务器)。
  • 使用第三方库以 JUnit 5 Extension 方式实现 WireMockRule 的等效功能,例如 https://github.com/lanwen/wiremock-junit5

请注意,您的问题已在JUnit 5 Issues中讨论过。


制作扩展程序的快捷方式请参考以下答案:https://dev59.com/p1UK5IYBdhLWcg3w_z60#66060677 - Ashley Frieze

14

JUnit 4的注解@Rule@ClassRule在JUnit 5中已经不存在了。现在有一个新的扩展模型可以用来实现具有相同功能的扩展。这些扩展可以使用@ExtendWith注解。

对于JUnit 4规则的子集,junit-jupiter-migrationsupport模块提供了有限的迁移支持。不幸的是,它仅限于ExternalResourceVerifier的子类。

在Wiremock正式支持JUnit之前,您可以采用以下一些解决方案:

  1. 使用junit-vintage-engine使JUnit 4测试与JUnit 5测试并行运行。
  2. 在测试代码中手动启动和停止服务器。
  3. 使用第三方扩展,如wiremock-junit5wiremock-extension

6

1

来自JUnit 5用户指南

@Rule@ClassRule已不再存在,被@ExtendWith@RegisterExtension取代。另请参见{{link2:“有限的JUnit 4规则支持”}}。

然而,正如Tom所指出的那样,自2.31.0版本以来,WireMock已经完全支持JUnit Jupiter:

// New JUnit 5 extension
@WireMockTest
class DeclarativeWireMockTest {

    @Test
    void test_something_with_wiremock(WireMockRuntimeInfo wmRuntimeInfo) {
        // The static DSL will be automatically configured for you
        stubFor(get("/static-dsl").willReturn(ok()));
      
        // Instance DSL can be obtained from the runtime info parameter
        WireMock wireMock = wmRuntimeInfo.getWireMock();
        wireMock.register(get("/instance-dsl").willReturn(ok()));
       
        // Info such as port numbers is also available
        int port = wmRuntimeInfo.getHttpPort();
        
        // Do some testing...
    }

}

如需更多信息,请参考相应文档


0

https://github.com/webcompere/java-test-gadgets 项目可以让你用几种方式来解决这个问题。

你可以使用它对 JUnit 4 规则的支持,通过 DangerousRuleAdapter - 它会尝试将任何 JUnit 4 规则转换为一个 Plugin

@ExtendWith(PluginExtension.class)
public class DangerousRuleAdapterExampleTest {
    @Plugin
    private DangerousRuleAdapter<WireMockRule> adapter = 
        new DangerousRuleAdapter<>(new WireMockRule());

    @Test
    void theTest() {
        // use wiremock rule here
        WireMockRule rule = adapter.get();
    }


规则适配器无法处理检查测试类或测试方法的规则,但可以尝试运行规则。
还支持在某些代码周围运行规则:
    TemporaryFolder temporaryFolder = new TemporaryFolder();

    // let's use this temp folder with some test code
    executeWithRule(temporaryFolder, () -> {
        // here, the rule is _active_
        callSomethingThatUses(temporaryFolder.getRoot());
    });

通过使用PluginExtensionTestResource.of,您可以轻松地创建自己的新JUnit 5插件

@ExtendWith(PluginExtension.class)
class TestResourceIsActiveDuringTest {
    private WireMockServer server;

    @Plugin
    private TestResource someResource = TestResource.from(() -> server.start(),
                                                          () -> server.stop());


1
危险规则...?哈哈。疯狂的命名选择 :)。 - Dut A.
@DutA. 我想要一个名字,让人们感到它可能并不总是起作用的原因。;) - Ashley Frieze

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