test(pipeline): 添加 Pipeline 核心功能测试

- 增加 Pipeline 执行流程测试,验证 Stage 和 Hook 的执行顺序
- 添加失败场景测试,确保 Pipeline 在失败时能正确停止并跳过后续阶段
- 实现 Stage 配置外部开关控制测试,验证可选 Stage 的启用与禁用逻辑
- 创建 RecordingContext 类用于记录执行事件,便于断言生命周期钩子调用
- 构建 SimpleStage 和 OptionalStage 测试辅助类,支持自定义执行逻辑与条件判断
This commit is contained in:
2025-12-03 22:15:05 +08:00
parent 60b4473279
commit af60cc1540

View File

@@ -0,0 +1,169 @@
package com.ycwl.basic.pipeline.core;
import com.ycwl.basic.pipeline.annotation.StageConfig;
import com.ycwl.basic.pipeline.enums.StageOptionalMode;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class PipelineTest {
@Test
void execute_shouldRunStagesAndHooks() {
RecordingContext context = new RecordingContext();
SimpleStage stage1 = new SimpleStage("stage1", ctx -> {
SimpleStage dynamic = new SimpleStage("stage1_dynamic", c -> StageResult.success());
return StageResult.successWithNext("add dynamic", dynamic);
});
SimpleStage stage2 = new SimpleStage("stage2", ctx -> StageResult.success());
Pipeline<RecordingContext> pipeline = new PipelineBuilder<RecordingContext>("recording")
.addStage(stage1)
.addStage(stage2)
.build();
boolean result = pipeline.execute(context);
assertTrue(result);
assertEquals(
List.of("before", "stage1", "stage1_dynamic", "stage2", "after", "cleanup"),
context.getEvents()
);
}
@Test
void execute_shouldStopOnFailureAndSkipAfterHook() {
RecordingContext context = new RecordingContext();
SimpleStage ok = new SimpleStage("ok", ctx -> StageResult.success());
SimpleStage fail = new SimpleStage("fail", ctx -> StageResult.failed("boom"));
SimpleStage neverRun = new SimpleStage("never", ctx -> StageResult.success());
Pipeline<RecordingContext> pipeline = new PipelineBuilder<RecordingContext>("failing")
.addStage(ok)
.addStage(fail)
.addStage(neverRun)
.build();
boolean result = pipeline.execute(context);
assertFalse(result);
assertEquals(
List.of("before", "ok", "fail", "cleanup"),
context.getEvents()
);
}
@Test
void stageConfigShouldRespectExternalSwitch() {
RecordingContext context = new RecordingContext();
context.setStageState("optional_stage", false);
OptionalStage optional = new OptionalStage();
Pipeline<RecordingContext> pipeline = new PipelineBuilder<RecordingContext>("optional")
.addStage(optional)
.build();
boolean result = pipeline.execute(context);
assertTrue(result);
assertEquals(
List.of("before", "after", "cleanup"),
context.getEvents()
);
}
/**
* 记录执行轨迹的 Context,便于断言 Pipeline 生命周期钩子与 Stage 执行顺序。
*/
static class RecordingContext implements PipelineContext {
private final List<String> events = new ArrayList<>();
private final Map<String, Boolean> stageStates = new HashMap<>();
@Override
public void beforePipeline() {
events.add("before");
}
@Override
public void afterPipeline() {
events.add("after");
}
@Override
public void cleanup() {
events.add("cleanup");
}
@Override
public boolean isStageEnabled(String stageId, boolean defaultEnabled) {
return stageStates.getOrDefault(stageId, defaultEnabled);
}
void setStageState(String stageId, boolean enabled) {
stageStates.put(stageId, enabled);
}
List<String> getEvents() {
return events;
}
}
/**
* 简化的 Stage 实现,支持自定义执行逻辑与业务前置条件。
*/
static class SimpleStage extends AbstractPipelineStage<RecordingContext> {
private final String name;
private final Function<RecordingContext, StageResult<RecordingContext>> executor;
private final Predicate<RecordingContext> condition;
SimpleStage(String name, Function<RecordingContext, StageResult<RecordingContext>> executor) {
this(name, executor, ctx -> true);
}
SimpleStage(String name,
Function<RecordingContext, StageResult<RecordingContext>> executor,
Predicate<RecordingContext> condition) {
this.name = name;
this.executor = executor;
this.condition = condition;
}
@Override
public String getName() {
return name;
}
@Override
protected boolean shouldExecuteByBusinessLogic(RecordingContext context) {
return condition.test(context);
}
@Override
protected StageResult<RecordingContext> doExecute(RecordingContext context) {
context.getEvents().add(name);
return executor.apply(context);
}
}
/**
* 带 StageConfig 的 Stage,用于验证 SUPPORT 模式下的开关控制。
*/
@StageConfig(stageId = "optional_stage", optionalMode = StageOptionalMode.SUPPORT, defaultEnabled = true)
static class OptionalStage extends SimpleStage {
OptionalStage() {
super("optional", ctx -> StageResult.success());
}
}
}