feat(sdk+msgcenter): 对齐 SDK 重构包名(openapi.client→base)+ 消息中心代理后端(09-16/09-19 遗漏提交)
build / build-push (push) Successful in 1m34s
build / build-push (push) Successful in 1m34s
- import 全面切换 com.yunhai.platform.openapi.base.*(对齐 Nexus -57 SDK)
- MsgCenter 代理三件(Properties/Controller/ProxyService)+ 测试 11/11(09-19 消息中心二期本地完成态)
- Dockerfile 已在 563edb5 去掉写死 profile;本提交补齐源码侧遗漏
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
package com.yunhai.userhome.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yunhai.platform.http.DHttpException;
|
||||
import com.yunhai.platform.utils.http.IDHttp;
|
||||
import com.yunhai.userhome.config.MsgCenterProperties;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.contains;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* 消息中心代理单测(§3.5,BP-R3-1):冻结 UserMsg oapi 契约
|
||||
* (list 信封 {total,content[]} / unreadCount 裸数字 / todo list 数组)与
|
||||
* jumpUrl 改写规则(jumpType=1 + bizType 命中基址 → 基址 + "/#" + jumpPath)。
|
||||
* UserMsg 不可达降级空结果(铃铛不 500)。
|
||||
*/
|
||||
@DisplayName("MsgCenterProxyService - UserMsg 代理与 jumpUrl 改写")
|
||||
class MsgCenterProxyServiceTest {
|
||||
|
||||
private IDHttp http;
|
||||
private MsgCenterProperties properties;
|
||||
private MsgCenterProxyService service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
http = mock(IDHttp.class);
|
||||
properties = new MsgCenterProperties();
|
||||
properties.setUsermsgBaseUrl("http://localhost:8080");
|
||||
properties.getJumpBases().put("flow.task", "http://localhost:8088/");
|
||||
service = new MsgCenterProxyService(http, properties, new ObjectMapper());
|
||||
}
|
||||
|
||||
private static com.fasterxml.jackson.databind.JsonNode json(String s) throws Exception {
|
||||
return new ObjectMapper().readTree(s);
|
||||
}
|
||||
|
||||
@Test
|
||||
void list_rewritesJumpUrlForFlowTask() throws Exception {
|
||||
properties.getAppNames().put("100617", "通知公告");
|
||||
when(http.get(contains("/oapi/msg/list?userId=201"), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenReturn(json("{\"total\":2,\"content\":["
|
||||
+ "{\"msgId\":1,\"title\":\"新待办\",\"content\":\"您有新的审批任务\",\"msgType\":2,"
|
||||
+ "\"jumpType\":1,\"jumpPath\":\"/task/123\",\"appKey\":\"100019\",\"bizType\":\"flow.task\","
|
||||
+ "\"bizId\":\"123\",\"sendTime\":\"2026-09-13 10:00:00\",\"isRead\":0},"
|
||||
+ "{\"msgId\":2,\"title\":\"无跳转\",\"content\":\"系统通知\",\"msgType\":0,"
|
||||
+ "\"jumpType\":0,\"jumpPath\":null,\"bizType\":null,\"isRead\":1}]}"));
|
||||
|
||||
Map<String, Object> out = service.list(201, 1, 10, null);
|
||||
assertEquals(2, out.get("total"));
|
||||
java.util.List<?> rows = (java.util.List<?>) out.get("list");
|
||||
Map<?, ?> first = (Map<?, ?>) rows.get(0);
|
||||
assertEquals("http://localhost:8088/#/task/123", first.get("jumpUrl"), "基址+/#+裸路径");
|
||||
assertEquals("flow.task", first.get("bizType"));
|
||||
assertNull(first.get("appName"), "未配置映射的 appKey 不补应用名");
|
||||
assertNull(((Map<?, ?>) rows.get(1)).get("jumpUrl"), "非应用内跳转不改写");
|
||||
}
|
||||
|
||||
@Test
|
||||
void list_appNameMappedFromAppKey() throws Exception {
|
||||
properties.getAppNames().put("100617", "通知公告");
|
||||
when(http.get(contains("/oapi/msg/list"), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenReturn(json("{\"total\":1,\"content\":[{\"msgId\":1,\"title\":\"通知公告\","
|
||||
+ "\"content\":\"您有一条通知\",\"msgType\":0,\"appKey\":\"100617\",\"isRead\":0}]}"));
|
||||
Map<String, Object> out = service.list(201, 1, 10, null);
|
||||
Map<?, ?> first = (Map<?, ?>) ((java.util.List<?>) out.get("list")).get(0);
|
||||
assertEquals("通知公告", first.get("appName"), "appKey 命中映射补应用名");
|
||||
}
|
||||
|
||||
@Test
|
||||
void wsTicket_returnsUrlWithTicket() throws Exception {
|
||||
properties.setUsermsgWsUrl("ws://localhost:8080/ws/msg");
|
||||
when(http.post(contains("/oapi/msg/ws/ticket"), any(Map.class), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenReturn(json("{\"ticket\":\"abc123ticket\",\"expiresIn\":60}"));
|
||||
String url = service.createWsTicket(201);
|
||||
assertEquals("ws://localhost:8080/ws/msg?ticket=abc123ticket", url);
|
||||
}
|
||||
|
||||
@Test
|
||||
void wsTicket_wsUrlNotConfigured_nullWithoutOutbound() {
|
||||
properties.setUsermsgWsUrl("");
|
||||
assertNull(service.createWsTicket(201));
|
||||
verify(http, never()).post(anyString(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void wsTicket_userMsgDown_degradesNull() {
|
||||
properties.setUsermsgWsUrl("ws://localhost:8080/ws/msg");
|
||||
when(http.post(contains("/oapi/msg/ws/ticket"), any(Map.class), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenThrow(new DHttpException("down", 0));
|
||||
assertNull(service.createWsTicket(201), "票据失败降级 null,前端不建立长连接");
|
||||
}
|
||||
|
||||
@Test
|
||||
void list_noBaseConfigured_jumpUrlNull() throws Exception {
|
||||
properties.getJumpBases().clear();
|
||||
when(http.get(contains("/oapi/msg/list"), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenReturn(json("{\"total\":1,\"content\":[{\"msgId\":1,\"jumpType\":1,"
|
||||
+ "\"jumpPath\":\"/task/9\",\"bizType\":\"flow.task\",\"isRead\":0}]}"));
|
||||
Map<String, Object> out = service.list(201, 1, 10, null);
|
||||
Map<?, ?> first = (Map<?, ?>) ((java.util.List<?>) out.get("list")).get(0);
|
||||
assertNull(first.get("jumpUrl"), "bizType 未配基址 → 不改写(前端不渲染跳转)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void list_userMsgDown_degradesToEmpty() {
|
||||
when(http.get(contains("/oapi/msg/list"), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenThrow(new DHttpException("DHttp request failed", 0));
|
||||
Map<String, Object> out = service.list(201, 1, 10, null);
|
||||
assertEquals(0, out.get("total"));
|
||||
assertEquals(0, ((java.util.List<?>) out.get("list")).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void summary_combinesUnreadAndTodos_withPerCallDegrade() throws Exception {
|
||||
when(http.get(contains("/oapi/msg/unreadCount"), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenReturn(json("3"));
|
||||
when(http.get(contains("/oapi/msg/todo/list"), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenReturn(json("[{\"appKey\":\"100019\",\"count\":2}]"));
|
||||
|
||||
Map<String, Object> out = service.summary(201, 1);
|
||||
assertEquals(3L, out.get("unreadCount"));
|
||||
assertEquals(1, ((java.util.List<?>) out.get("todos")).size());
|
||||
|
||||
// 未读数不可达单独降级为 0,待办仍可用
|
||||
when(http.get(contains("/oapi/msg/unreadCount"), eq(com.fasterxml.jackson.databind.JsonNode.class)))
|
||||
.thenThrow(new DHttpException("down", 0));
|
||||
Map<String, Object> out2 = service.summary(201, 1);
|
||||
assertEquals(0L, out2.get("unreadCount"));
|
||||
assertEquals(1, ((java.util.List<?>) out2.get("todos")).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void read_sendsOwnerScopedPayload() {
|
||||
service.read(201, java.util.Collections.singletonList(7L));
|
||||
verify(http).post(contains("/oapi/msg/read"), any(Map.class), eq(com.fasterxml.jackson.databind.JsonNode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void disabled_degradesWithoutOutbound() {
|
||||
properties.setUsermsgBaseUrl("");
|
||||
assertEquals(0, service.list(201, 1, 10, null).get("total"));
|
||||
service.read(201, java.util.Collections.singletonList(7L));
|
||||
verify(http, never()).get(anyString(), any());
|
||||
verify(http, never()).post(anyString(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void summary_disabled_degradesToZero() {
|
||||
properties.setUsermsgBaseUrl("");
|
||||
Map<String, Object> out = service.summary(201, 1);
|
||||
assertEquals(0L, out.get("unreadCount"));
|
||||
assertEquals(0, ((java.util.List<?>) out.get("todos")).size());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user