如何在Karate DSL的TestRunner中正确配置多个Hook类?
问题描述
我使用Karate 1.4.0版本,以下是TestRunner.java的代码片段:
... @Test public void testParallel() { Results results = Runner.path("classpath:") .tags("~@ignore") .outputCucumberJson(true) .outputJunitXml(true) .hook(new KarateHook()) .hook(new AnotherHook()) .parallel(4); generateReport(results.getReportDir()); Assertions.assertThat(results.getFailCount()) .withFailMessage(String.format("There are %s failing scenarios.", results.getFailCount())) .isZero(); } ...
如上所示,我使用了两个来自不同类的Hook。KarateHook()和AnotherHook()的核心代码如下:
KarateHook.java:
... @Override public void afterScenario(ScenarioRuntime sr) { LOGGER.info("THIS IS DEFAULT afterScenario HOOK"); } ...
AnotherHook.java:
... @Override public void afterScenario(ScenarioRuntime sr) { LOGGER.info("THIS IS THE OTHER afterScenario HOOK"); } ...
我期望执行单个Scenario A时的输出为:
<Scenario A ran and success> - THIS IS DEFAULT afterScenario HOOK - THIS IS THE OTHER afterScenario HOOK
但实际得到的输出是:
<Scenario A ran and success> - THIS IS DEFAULT afterScenario HOOK <Scenario A ran AGAIN and success> - THIS IS THE OTHER afterScenario HOOK
我尝试改用.hooks方法:
@Test public void testParallel() { List<RuntimeHook> karateHooks = new ArrayList<>(); karateHooks.add(new KarateHook()); karateHooks.add(new AnotherHook()); Results results = Runner.path("classpath:") .tags("~@ignore") .outputCucumberJson(true) .outputJunitXml(true) .hooks(karateHooks) .parallel(4); }
但问题依然存在,请问正确实现预期效果的方法是什么?
解决方案
出现场景重复执行的核心原因是自定义Hook类没有正确继承Karate的BaseHook抽象类,或是错误重写apply()方法导致场景生命周期流程异常。
按照以下步骤修复:
修改Hook类继承
BaseHook
所有自定义Hook需要继承com.intuit.karate.core.BaseHook,而非直接实现RuntimeHook接口。BaseHook已实现RuntimeHook的核心方法,能正确管理场景生命周期:// KarateHook.java import com.intuit.karate.core.BaseHook; import com.intuit.karate.core.ScenarioRuntime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class KarateHook extends BaseHook { private static final Logger LOGGER = LoggerFactory.getLogger(KarateHook.class); @Override public void afterScenario(ScenarioRuntime sr) { LOGGER.info("THIS IS DEFAULT afterScenario HOOK"); } }// AnotherHook.java import com.intuit.karate.core.BaseHook; import com.intuit.karate.core.ScenarioRuntime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AnotherHook extends BaseHook { private static final Logger LOGGER = LoggerFactory.getLogger(AnotherHook.class); @Override public void afterScenario(ScenarioRuntime sr) { LOGGER.info("THIS IS THE OTHER afterScenario HOOK"); } }保留原Runner配置即可
无论是多次调用.hook()还是使用.hooks()传入列表,只要Hook类继承了BaseHook,就能保证场景只执行一次,所有Hook的afterScenario会在场景执行完成后依次触发:// 方式1:多次调用hook() Results results = Runner.path("classpath:") .tags("~@ignore") .outputCucumberJson(true) .outputJunitXml(true) .hook(new KarateHook()) .hook(new AnotherHook()) .parallel(4); // 方式2:使用hooks()传入列表 List<RuntimeHook> karateHooks = new ArrayList<>(); karateHooks.add(new KarateHook()); karateHooks.add(new AnotherHook()); Results results = Runner.path("classpath:") .tags("~@ignore") .outputCucumberJson(true) .outputJunitXml(true) .hooks(karateHooks) .parallel(4);(可选)升级Karate版本
如果上述修改后问题仍存在,建议升级到Karate 1.5.0及以上版本,1.4.0版本存在一些Hook相关的已知问题,新版本已修复。
内容的提问来源于stack exchange,提问作者Aaron Purnomo Murniadi
相关产品推荐
相关产品推荐

