package com.yunhai.svchall.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yunhai.platform.openapi.core.YschOpenCall;
import com.yunhai.platform.openapi.flow.YschFlowOpenApi;
import com.yunhai.platform.openapi.flow.impl.DefaultOpenApiFlowClient;
import com.yunhai.platform.openapi.flow.model.FlowApplyBody;
import com.yunhai.platform.openapi.flow.model.FlowCallbackRegBody;
import com.yunhai.svchall.model.svc.SvcModels;
import com.yunhai.svchall.service.FlowClient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* svc-hall → flow-center 出站契约测试:服务目录显式配置 {@code flowcenter} 时,
* 全部出站(listFlows / getFlow / apply / instance / callback·reg)必须走 SDK 命名目标
* (门面 {@link YschFlowOpenApi} 或预绑 {@code BoundOpenCall}),不再回落应用专属
* {@code svchall.flow.base-url}(《子应用配置优化方案》§4.2 零专属地址配置)。
* 此前只有 listFlows/getFlow 走门面,apply/instance/registerCallback 仍用 ad-hoc
* {@code TargetSpec.of(baseUrl,"")}——地址仍来自应用配置,且 {@code hasTarget} 探测与真实调用
* 分支不一致(探测说"目录已配",调用却打 legacy 地址)。
*/
@DisplayName("svc-hall FlowCenterClient - 服务目录命名目标(全端点)")
class FlowCenterClientFacadeTest {
private static final String TARGET = "flow-center";
private static final String LEGACY_BASE = "http://flow-center-service:10008/flow-center";
private final ObjectMapper objectMapper = new ObjectMapper();
private YschOpenCall openCall;
@BeforeEach
void setUp() {
openCall = mock(YschOpenCall.class);
when(openCall.hasTarget(TARGET)).thenReturn(true);
// 门面静态入口:setCall 由被测类构造器完成,setClient 由 starter 完成——单测手工对齐装配
YschFlowOpenApi.setCall(openCall);
YschFlowOpenApi.setClient(new DefaultOpenApiFlowClient(openCall));
}
private FlowCenterClient client() {
return new FlowCenterClient(openCall, objectMapper, true, LEGACY_BASE);
}
@Test
@DisplayName("apply:走门面 → 命名目标 + SDK FlowApplyBody 子类 + 出参 instanceId/duplicated")
void apply_goesThroughFacade() {
SvcModels.ApplyResultVo stub = new SvcModels.ApplyResultVo();
stub.setInstanceId(5L);
stub.setDuplicated(true);
when(openCall.post(eq(TARGET), eq("/oapi/flow/apply"), anyMap(),
any(FlowApplyBody.class), eq(SvcModels.ApplyResultVo.class))).thenReturn(stub);
FlowClient.ApplyResult result = client().apply(3L, "guid-1", "svc_item", "1", "刘文娟的教师入职",
"http://base.yunhai/svc-hall/front/#/apply-detail?id=1", "{\"a\":1}", 10133, "刘文娟", null);
assertEquals(Long.valueOf(5L), result.getInstanceId());
assertTrue(result.isDuplicated());
ArgumentCaptor body = ArgumentCaptor.forClass(FlowApplyBody.class);
ArgumentCaptor