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

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

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

我想切换到 JUnit 5,所以我添加了下一个依赖项(使用 Gradle) :

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

但是,当我试图导入 @Rule注释时,没有任何建议。

我是否需要添加另一个 JUnit 依赖模块?还是 JUnit5不支持规则?如果没有,我如何替换 @Rule注释使测试再次工作?

66256 次浏览

In a general way, what you did with @Rule and @ClassRule in JUnit 4 should be done with @ExtendWith and Extension that associated provide a very close feature in JUnit 5.
It works as standards JUnit lifecycle hooks but that it is extracted in a Extension class. And similarly to @Rule, as many Extensions as required may be added for a test class.

To handle the issue you have several possible approaches among :

  • keep the JUnit 4 way (JUnit 5 owns the JUnit Vintage part that allows to execute JUnit 3 or 4 tests).
  • rewrite the @Rule as an Extension.
  • do the actual processing done by WireMockRule (start the server, execute your tests and stop the server) in each test of class with @BeforeEach and @AfterEach hook methods.
  • use a third library that implements the equivalent of WireMockRule in the JUnit 5 Extension way such as https://github.com/lanwen/wiremock-junit5

Note that your issue already discussed in the JUnit 5 Issues.

JUnit 4 annotations @Rule and @ClassRule do not exist in JUnit 5. Basically there is a new extension model that can be used to implement extensions with the same functionality. These extensions can be used with the @ExtendWith annotation.

There is a limited migration support for a subset of JUnit 4 rules in the junit-jupiter-migrationsupport module. Unfortunately, it's only limited to subclasses of ExternalResource and Verifier.

Before wiremock has official support for JUnit you have some workarounds:

  1. Run JUnit 4 tests side by side with JUnit 5 tests with the junit-vintage-engine.
  2. Start and stop the server yourself in the test code.
  3. Use a 3rd party extension like wiremock-junit5 or wiremock-extension.

The https://github.com/webcompere/java-test-gadgets project lets you solve this in a couple of ways.

You can use its support for JUnit 4 rules via the DangerousRuleAdapter - which will attempt to turn any JUnit 4 rule into a 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();
}


The rule adapters cannot work with rules that inspect the test class or the test method, but make a good attempt at running the rule.

There's also support for running a rule around some code:

    TemporaryFolder temporaryFolder = new TemporaryFolder();


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

And you can easily create your own new JUnit 5 plugin by using the PluginExtension and TestResource.of

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


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


From the JUnit 5 user guide:

@Rule and @ClassRule no longer exist; superseded by @ExtendWith and @RegisterExtension. See also "Limited JUnit 4 Rule Support".

However, as pointed out by Tom, WireMock has full JUnit Jupiter support since version 2.31.0:

// 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...
}


}

For more information, please refer to the corresponding docs.

There is now official support for JUnit 5 Jupiter from WireMock 2.31.0.

Docs here: http://wiremock.org/docs/junit-jupiter/