如何在JUnit 5 Jupiter中运行JBehave测试?
JBehave在JUnit 5环境中的迁移方案
好消息是JBehave完全可以在JUnit 5环境中运行!虽然官方目前还没有提供原生的JUnit 5扩展,但我们可以绕开原来JUnit 4的@RunWith机制,让JUnit 5直接托管JBehave的执行逻辑,具体操作如下:
核心思路
原来的JUnit 4通过@RunWith(AnnotatedEmbedderRunner.class)让JUnit托管JBehave的执行流程,而JUnit 5没有对应的扩展支持。我们的解决办法是:把JBehave的故事执行逻辑封装到一个JUnit 5的@Test方法中,让JUnit 5识别这个测试方法,内部手动启动JBehave的Embedder来运行所有故事。
调整测试类代码
下面是修改后的JBehaveTest类,我标注了关键的修改点:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.jbehave.core.Embeddable; import org.jbehave.core.Embedder; import org.jbehave.core.configuration.MostUsefulConfiguration; import org.jbehave.core.io.CodeLocations; import org.jbehave.core.io.StoryFinder; import org.jbehave.core.reporters.DetailedStepReporter; import org.jbehave.core.reporters.Format; import org.jbehave.core.reporters.StoryReporterBuilder; import org.jbehave.core.steps.InstanceStepsFactory; import org.jbehave.core.steps.Steps; import org.jbehave.core.reporters.DotStoryReporter; import org.testfx.api.FxToolkit; import javafx.stage.Stage; import java.io.File; import java.util.Collections; import java.util.Locale; import java.util.concurrent.TimeoutException; public class JBehaveTest implements Embeddable { private Embedder embedder; private DotStoryReporter dot = new DotStoryReporter(); private Stage primaryStage; // 替换JUnit 4的@Before为JUnit 5的@BeforeEach @BeforeEach public void createStage() throws TimeoutException { Locale locale = new Locale("fa", "IR"); Locale.setDefault(locale); primaryStage = FxToolkit.registerPrimaryStage(); } // JUnit 5识别的唯一测试方法,内部触发所有JBehave故事执行 @Test public void runJBehaveStories() throws Throwable { initEmbedder(); // 运行所有匹配的.story文件 embedder.runStoriesAsPaths(new StoryFinder().findPaths( "src/test/resources", Collections.singletonList("**/*.story"), Collections.emptyList() )); // 验证执行结果,让JUnit 5感知故事执行的成败 if (!embedder.getEmbedderControls().isIgnoreFailureInStories()) { org.junit.jupiter.api.Assertions.assertTrue( embedder.getFailureCount() == 0, "JBehave故事执行失败,失败数量: " + embedder.getFailureCount() ); } } // 手动初始化Embedder和配置,替代原来@UsingEmbedder的作用 private void initEmbedder() { embedder = new Embedder(); MostUsefulConfiguration configuration = new MostUsefulConfiguration(); Steps steps = new Steps(); // 配置报告生成逻辑,和原来保持一致 configuration.useStoryReporterBuilder( new StoryReporterBuilder() .withCodeLocation(CodeLocations.codeLocationFromClass(JBehaveTest.class)) .withDefaultFormats() .withReporters(dot, new MyStoryReporter(new File("test"), steps)) .withFormats(Format.HTML, Format.TXT) .withFailureTrace(true) .withFailureTraceCompression(false) ); configuration.useStepdocReporter(new DetailedStepReporter()); // 绑定Steps类和配置 embedder.useStepsFactory(new InstanceStepsFactory(configuration, steps)); embedder.useConfiguration(configuration); // 手动设置原来@UsingEmbedder中的参数 embedder.embedderControls() .useVerboseFailures(true) .doIgnoreFailureInStories(false) .doGenerateViewAfterStories(true); } @Override public void useEmbedder(Embedder embedder) { this.embedder = embedder; } }
调整Gradle依赖
原来的de.codecentric:jbehave-junit-runner是JUnit 4专属的运行器,现在可以移除了,其他依赖保持不变即可:
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.2.0' testImplementation 'org.mockito:mockito-core:2.18.3' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.2.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.2.0' testImplementation 'org.testfx:testfx-core:4.0.+' testImplementation 'org.testfx:testfx-junit5:4.0.+' testImplementation 'org.jbehave:jbehave-core:4.3.2' // 移除JUnit 4的JBehave运行器 // testCompile 'de.codecentric:jbehave-junit-runner:1.2.0'
关键注意事项
- 确保
StoryFinder的路径参数和你的项目结构匹配,避免找不到故事文件 - 如果有自定义的Steps类,要在
InstanceStepsFactory的构造参数中添加进去(比如new InstanceStepsFactory(configuration, steps, customStep1, customStep2)) - JBehave的报告生成逻辑不受影响,依然会按照配置输出HTML、TXT等格式的报告
内容的提问来源于stack exchange,提问作者M. le Rutte
相关产品推荐
相关产品推荐

