package cn.iocoder.yudao.module.mes.framework.config;
|
|
import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
import java.util.List;
|
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.Mockito.*;
|
|
/**
|
* 字典解析器测试:守住「字典优先、配置文件兜底」的合并规则与「绝不抛异常」的约定。
|
*/
|
class MesTraceConfigResolverTest {
|
|
private static final String YAML_URL = "http://yaml.example.org/trace.html";
|
private static final String DICT_URL = "http://1.95.78.124:9008/prod/trace.html";
|
|
private final DictDataApi dictDataApi = mock(DictDataApi.class);
|
|
@Test
|
void dictValueWinsOverYaml() {
|
stubDict(dict("追溯网址", DICT_URL));
|
|
MesTraceConfigSnapshot snapshot = newResolver().resolveSnapshot();
|
|
assertEquals(DICT_URL, snapshot.traceUrl());
|
assertEquals(MesTraceUrlSource.DICT, snapshot.traceUrlSource());
|
}
|
|
@Test
|
void fallsBackToYamlWhenDictTypeMissing() {
|
stubDict(); // 字典类型尚未初始化,属于正常的「尚未配置」路径
|
|
MesTraceConfigSnapshot snapshot = newResolver().resolveSnapshot();
|
|
assertEquals(YAML_URL, snapshot.traceUrl());
|
assertEquals(MesTraceUrlSource.YAML, snapshot.traceUrlSource());
|
}
|
|
@Test
|
void disabledDictItemIsTreatedAsAbsent() {
|
// 禁用是不删数据即停用某项配置的手段,必须按「未配置」处理
|
DictDataRespDTO disabled = dict("追溯网址", DICT_URL);
|
disabled.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
stubDict(disabled);
|
|
MesTraceConfigSnapshot snapshot = newResolver().resolveSnapshot();
|
|
assertEquals(YAML_URL, snapshot.traceUrl());
|
assertEquals(MesTraceUrlSource.YAML, snapshot.traceUrlSource());
|
}
|
|
@Test
|
void blankDictValueFallsBackToYaml() {
|
stubDict(dict("追溯网址", " "));
|
|
MesTraceConfigSnapshot snapshot = newResolver().resolveSnapshot();
|
|
assertEquals(YAML_URL, snapshot.traceUrl());
|
assertEquals(MesTraceUrlSource.YAML, snapshot.traceUrlSource());
|
}
|
|
@Test
|
void invalidDictValueFallsBackToYamlAndFlagsSource() {
|
// 字典里填了内网地址:降级回配置文件而不是抛异常,避免一次手误让全平台导出停摆
|
stubDict(dict("追溯网址", "http://192.168.1.1/trace.html"));
|
|
MesTraceConfigSnapshot snapshot = newResolver().resolveSnapshot();
|
|
assertEquals(YAML_URL, snapshot.traceUrl());
|
assertEquals(MesTraceUrlSource.YAML_INVALID_DICT, snapshot.traceUrlSource());
|
}
|
|
@Test
|
void dictReadFailureFallsBackToYamlWithoutThrowing() {
|
when(dictDataApi.getDictDataList(MesTraceConfigResolver.DICT_TYPE))
|
.thenThrow(new RuntimeException("数据库抖动"));
|
|
MesTraceConfigSnapshot snapshot = assertDoesNotThrow(() -> newResolver().resolveSnapshot());
|
|
assertEquals(YAML_URL, snapshot.traceUrl());
|
assertEquals(MesTraceUrlSource.YAML, snapshot.traceUrlSource());
|
}
|
|
@Test
|
void dictIsReadOncePerCacheWindow() {
|
stubDict(dict("追溯网址", DICT_URL));
|
MesTraceConfigResolver resolver = newResolver();
|
|
resolver.resolveSnapshot();
|
resolver.resolveSnapshot();
|
resolver.resolveSnapshot();
|
|
// 标签导出会成千上万次取快照,绝不能每次都查库
|
verify(dictDataApi, times(1)).getDictDataList(MesTraceConfigResolver.DICT_TYPE);
|
}
|
|
@Test
|
void resolvesOtherFieldsIndependentlyFromDict() {
|
stubDict(dict("追溯网址", DICT_URL),
|
dict("生产经营者名称", "新疆塔里木河种业股份有限公司"),
|
dict("进口商名称", "某进口商"),
|
dict("是否进口种子", "true"));
|
|
MesTraceConfigSnapshot snapshot = newResolver().resolveSnapshot();
|
|
assertEquals("新疆塔里木河种业股份有限公司", snapshot.operatorName());
|
assertEquals("某进口商", snapshot.importerName());
|
assertTrue(snapshot.imported());
|
}
|
|
@Test
|
void fieldsFallBackIndependentlyWhenOnlyUrlIsConfigured() {
|
// 只配了追溯网址:其余三项仍应回退配置文件,而不是被清空
|
stubDict(dict("追溯网址", DICT_URL));
|
|
MesTraceConfigSnapshot snapshot = newResolver().resolveSnapshot();
|
|
assertEquals(DICT_URL, snapshot.traceUrl());
|
assertEquals("YAML 生产经营者", snapshot.operatorName());
|
assertEquals("YAML 进口商", snapshot.importerName());
|
assertFalse(snapshot.imported());
|
}
|
|
@Test
|
void unrecognizedImportedValueFallsBackToYaml() {
|
stubDict(dict("是否进口种子", "也许吧"));
|
|
assertFalse(newResolver().resolveSnapshot().imported());
|
}
|
|
@Test
|
void firstEnabledItemWinsWhenDuplicated() {
|
// 同一标签重复配置时以排序靠前者为准(底层查询已按 sort 排序)
|
stubDict(dict("追溯网址", DICT_URL), dict("追溯网址", "http://second.example.org/trace.html"));
|
|
assertEquals(DICT_URL, newResolver().resolveSnapshot().traceUrl());
|
}
|
|
private MesTraceConfigResolver newResolver() {
|
MesTraceConfigResolver resolver = new MesTraceConfigResolver();
|
MesProperties properties = new MesProperties();
|
properties.setTraceBaseUrl(YAML_URL);
|
properties.setOperatorName("YAML 生产经营者");
|
properties.setImporterName("YAML 进口商");
|
properties.setImported(false);
|
ReflectionTestUtils.setField(resolver, "dictDataApi", dictDataApi);
|
ReflectionTestUtils.setField(resolver, "mesProperties", properties);
|
return resolver;
|
}
|
|
private void stubDict(DictDataRespDTO... data) {
|
when(dictDataApi.getDictDataList(MesTraceConfigResolver.DICT_TYPE)).thenReturn(List.of(data));
|
}
|
|
private static DictDataRespDTO dict(String label, String value) {
|
DictDataRespDTO dto = new DictDataRespDTO();
|
dto.setDictType(MesTraceConfigResolver.DICT_TYPE);
|
dto.setLabel(label);
|
dto.setValue(value);
|
dto.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
return dto;
|
}
|
|
}
|