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

Posted

技术标签:

【中文标题】如何在 JUnit 5 中替换 WireMock @Rule 注释?【英文标题】:How to replace WireMock @Rule annotation in JUnit 5? 【发布时间】:2018-12-03 08:55:16 【问题描述】:

我在我的测试中使用了 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 注释以使测试再次工作?

【问题讨论】:

查看这篇精彩的文章codeaffine.com/2016/04/06/replace-rules-in-junit5 没有直接替换,Junit Jupiter使用@Extension而不是@Rlue;开发人员需要移植他们的代码 - WireMock 还没有 done this yes。您可以自己实现@Extension 【参考方案1】:

一般而言,您在 JUnit 4 中对 @Rule@ClassRule 所做的操作应该使用 @ExtendWithExtension 完成,它们在 JUnit 5 中提供了非常接近的功能。 它作为标准的 JUnit 生命周期钩子工作,但它是在 Extension 类中提取的。与@Rule 类似,可以为测试类添加任意数量的Extensions。

要处理这个问题,您有几种可能的方法:

保持 JUnit 4 方式(JUnit 5 拥有允许执行 JUnit 3 或 4 测试的 JUnit Vintage 部分)。 将@Rule 重写为Extension。 使用@BeforeEach@AfterEach 钩子方法在类的每个测试中执行WireMockRule 完成的实际处理(启动服务器、执行测试和停止服务器)。 使用第三个库,该库在 JUnit 5 扩展方式中实现 WireMockRule 的等价物,例如 https://github.com/lanwen/wiremock-junit5

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

【讨论】:

有关制作扩展的快捷方式,请参阅答案***.com/a/66060677/1355930【参考方案2】:

JUnit 4 注释 @Rule@ClassRule 在 JUnit 5 中不存在。基本上有一个新的扩展模型可用于实现具有相同功能的扩展。这些扩展可以与@ExtendWith 注解一起使用。

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

在wiremock 正式支持JUnit 之前,您有一些解决方法:

    使用 junit-vintage-engine 同时运行 JUnit 4 测试和 JUnit 5 测试。 在测试代码中自行启动和停止服务器。 使用第 3 方扩展程序,例如 wiremock-junit5 或 wiremock-extension。

【讨论】:

【参考方案3】:

现在正式支持 WireMock 2.31.0 中的 JUnit 5 Jupiter。

这里的文档:http://wiremock.org/docs/junit-jupiter/

【讨论】:

【参考方案4】:

https://github.com/webcompere/java-test-gadgets 项目可让您通过多种方式解决此问题。

您可以通过 DangerousRuleAdapter 使用它对 JUnit 4 规则的支持 - 这将尝试将任何 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());

【讨论】:

DangerousRule...?哈哈。疯狂的名字选择:)。 @DutA。我想要一个能让人们了解为什么它可能并不总是有效的名字;)【参考方案5】:

来自JUnit 5 user guide:

@Rule@ClassRule 不再存在;被@ExtendWith@RegisterExtension 取代。另见"Limited JUnit 4 Rule Support"。

不过,正如pointed out by Tom,WireMock 自 2.31.0 版起已全面支持 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...
    


更多信息请参考corresponding docs。

【讨论】:

以上是关于如何在 JUnit 5 中替换 WireMock @Rule 注释?的主要内容,如果未能解决你的问题,请参考以下文章

使用 WireMock 的 Spring JUnit 测试中的多个应用程序上下文

使用wiremock时连接被拒绝

如何在 JUnit Test Java 中替换 Mockito 以存根类

如何在 WireMock 中使请求文件先于另一个文件执行?

如何根据使用wiremock和JSON的请求正文匹配获得响应

Wiremock Stand alone - 如何使用请求数据操作响应